Как отобразить, добавлена ​​или удалена коллекция? - PullRequest
0 голосов
/ 19 декабря 2010

Во-первых, я прошу прощения за размещение аналогичного вопроса на "4462626". Я хочу сравнить с двумя объектами (которые являются отношениями родитель-ребенок). Как вы думаете, следующий код. Я думаю, что это не эффективно, потому что существует слишком много циклов for. Можете ли вы посоветовать мне? (обратите внимание: мне не разрешено изменять Item.class, а ItemEx.class должен расширять Item.class)

EXPECTED RESULT
------------------------
add:4
delete:2
------------------------

package com.javastudy;

import java.util.ArrayList;
import java.util.List;

public class CollectionCompareToObjectsForLoop {

 public static void main(String[] args) {

  List<Item> beforeList = new ArrayList<Item>();
  List<ItemEx> afterList = new ArrayList<ItemEx>();

  beforeList.add(new Item(1L));
  beforeList.add(new Item(2L)); // delete
  beforeList.add(new Item(3L));

  afterList.add(new ItemEx(1L));
  afterList.add(new ItemEx(3L));
  afterList.add(new ItemEx(4L)); // added

  // Check Add
  List<Item> addList = new ArrayList<Item>();
  for(Item afterItem : afterList){
   if(checkAdd(afterItem, beforeList)){
    addList.add(afterItem);
   }
  }

  // Check Delete
  List<Item> deleteList = new ArrayList<Item>();
  for(Item beforeItem : beforeList){
   if(checkDelete(beforeItem, afterList)){
    deleteList.add(beforeItem);
   }
  }

  // Print Result
  for(Item item : addList){
   System.out.println("add:" + item.getId());
  }
  for(Item item : deleteList){
   System.out.println("delete:" + item.getId());
  }

 }

 private static boolean checkAdd(Item afterItem, List<Item> beforeList) {
  for(Item beforeItem : beforeList){
   if (afterItem.getId().equals(beforeItem.getId())){
    return false;
   }
  }
  return true;
 }

 private static boolean checkDelete(Item beforeItem, List<ItemEx> afterList) {
  for(Item afterItem : afterList){
   if (beforeItem.getId().equals(afterItem.getId())){
    return false;
   }
  }
  return true;
 }

}

package com.javastudy;

public class Item {

 private Long id;

 public Item(Long id) {
  this.id = id;
 }

 public Long getId() {
  return id;
 }

 public void setId(Long id) {
  this.id = id;
 }

}

package com.javastudy;

public class ItemEx extends Item {

 private String name;

 public ItemEx(Long id) {
  super(id);
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

}

Ответы [ 2 ]

0 голосов
/ 19 декабря 2010

Я предполагаю, что Id, которые вы дали элементам, на самом деле являются идентификаторами, так что элементы с одинаковым идентификатором считаются равными, и что для каждого идентификатора имеется только один элемент.Затем вы можете использовать следующий код:

package so4483619;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class AddDel {

  private static <K, V> HashMap<K, V> newLinkedHashMap() {
    return new LinkedHashMap<K, V>();
  }

  private static <K, V> HashMap<K, V> newLinkedHashMap(Map<? extends K, ? extends V> other) {
    return new LinkedHashMap<K, V>(other);
  }

  private static void computeDeleteAndAdd(List<? extends Item> before, List<? extends Item> after) {
    Map<Long, Item> beforeById = newLinkedHashMap();
    for (Item item : before) {
      beforeById.put(item.getId(), item);
    }

    Map<Long, Item> afterById = newLinkedHashMap();
    for (Item item : after) {
      afterById.put(item.getId(), item);
    }

    Map<Long, Item> onlyBefore = newLinkedHashMap(beforeById);
    onlyBefore.keySet().removeAll(afterById.keySet());

    Map<Long, Item> onlyAfter = newLinkedHashMap(afterById);
    onlyAfter.keySet().removeAll(beforeById.keySet());

    for (Map.Entry<Long, Item> entry : onlyBefore.entrySet()) {
      System.out.println("delete:" + entry.getKey());
    }
    for (Map.Entry<Long, Item> entry : onlyAfter.entrySet()) {
      System.out.println("add:" + entry.getKey());
    }
  }

  public static void main(String[] args) {
    List<Item> beforeList = new ArrayList<Item>();
    List<ItemEx> afterList = new ArrayList<ItemEx>();

    beforeList.add(new Item(1L));
    beforeList.add(new Item(2L)); // delete
    beforeList.add(new Item(3L));

    afterList.add(new ItemEx(1L));
    afterList.add(new ItemEx(3L));
    afterList.add(new ItemEx(4L));

    computeDeleteAndAdd(beforeList, afterList);
  }
}

Некоторые замечания:

  • LinkedHashMap ведет себя как карта, но запоминает порядок, в котором элементы были вставлены.Это сделано для того, чтобы вывод был предсказуемым и имел тот же порядок, что и в beforeList и afterList.
  • Ваши классы Item и ItemEx не имеют методов equals(Object) и hashCode(), поэтому их нельзя использовать непосредственно как ключи в HashMap.Это мое предположение, что вы считаете, что два Item с одинаковым идентификатором равны.
  • Два вспомогательных метода newLinkedHashMap просто сохраняют некоторые нажатия клавиш в методе computeDeleteAndAdd.Без этих методов вы должны были бы сказать new LinkedHashMap<Long, Item>(...) вместо простого newLinkedHashMap(...).
0 голосов
/ 19 декабря 2010

Это решение теряет порядок списков ...

Set<Item> added = new HashSet<Item>(afterList);
Set<Item> removed = new HashSet<Item>(beforeList);
added.removeAll(beforeList);
removed.removeAll(afterList);
for(Item item : added){
   System.out.println("add:" + item.getId());
}
for(Item item : removed){
   System.out.println("delete:" + item.getId());
}
...