2010-12-19 14 views
0

Erstens, ich entschuldige mich dafür, eine ähnliche Frage zu "4462626" zu stellen. Ich möchte mit zwei Objekten (die Eltern-Kind-Beziehung sind) vergleichen. Wie denkst du, folgenden Code? Ich denke, es ist nicht effizient, weil zu viele for-Schleifen existieren. Kannst du mich beraten? (Beachten Sie: Ich bin nicht Item.class zu modifizieren erlaubt und ItemEx.class müssen Item.class verlängern)Wie wird angezeigt, ob eine Sammlung hinzugefügt oder gelöscht wurde?

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; 
} 

} 

Antwort

0

Ich gehe davon aus, dass Die Id s, die du den Items gegeben hast, sind wirklich IDs, so dass Items mit der gleichen ID als gleich angesehen werden und dass es nur einen Item pro ID gibt. Dann können Sie den folgenden Code verwenden:

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); 
    } 
} 

Einige Bemerkungen:

  • Die LinkedHashMap verhält sich wie eine Karte, aber erinnert sich an die Reihenfolge, in der die Elemente eingefügt wurden. Dies dient dazu, die Ausgabe vorhersagbar zu machen und die gleiche Reihenfolge wie in beforeList und afterList zu haben.
  • Ihre Klassen Item und ItemEx nicht über die Methoden equals(Object) und hashCode(), so dass sie nicht direkt als Schlüssel in einem HashMap verwendet werden. Dies ist meine Annahme, dass Sie zwei Item s mit der gleichen ID als gleich betrachten.
  • Die zwei Hilfsmethoden newLinkedHashMap speichern Sie nur einige Tastenanschläge in der Methode computeDeleteAndAdd. Ohne diese Methoden müssten Sie anstelle eines einfachen newLinkedHashMap(...)new LinkedHashMap<Long, Item>(...) sagen.
0

Diese Lösung verliert die Reihenfolge der Listen ...

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

Stellen Sie sicher, dass 'Item' die Parameter' equals' und 'hashCode' überschreibt. – finnw

+0

@finnw: ausgezeichneter Punkt. Ich hätte diese Annahme hinzufügen sollen. –

Verwandte Themen