首先,我为将类似问题发布到“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;
}
}
答案 0 :(得分:0)
此解决方案失去了列表的顺序......
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());
}
答案 1 :(得分:0)
我假设您为项目提供的Id
实际上是ID,因此具有相同ID的项目被认为是相同的,并且每个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
中的关键字。我假设您认为具有相同ID的两个Item
是相同的。newLinkedHashMap
只是在方法computeDeleteAndAdd
中保存了一些按键。如果没有这些方法,您必须说new LinkedHashMap<Long, Item>(...)
而不是简单的newLinkedHashMap(...)
。