开发者

How to display whether a collection added or deleted?

开发者 https://www.devze.com 2023-01-31 13:16 出处:网络
Firstly, I apologize for posting similar question to \"4462626\". I want to compare to two objects (which are parent-child relationship). How do you think following code. I think it is not efficient b

Firstly, I apologize for posting similar question to "4462626". I want to compare to two objects (which are parent-child relationship). How do you think following code. I think it is not efficient because too many for-loops exist. Can you advice me? (notice: I am not allowed to modify Item.class and ItemEx.class must extend 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(Ite开发者_运维百科m 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;
 }

}


I assume that the Ids you gave to the items are really IDs, so that items having the same ID are considered equal and that there is only one item per ID. Then you can use the following code:

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

Some remarks:

  • The LinkedHashMap behaves like a map but remembers the order in which the elements have been inserted. This is to make the output predictable and to have the same order as in the beforeList and afterList.
  • Your classes Item and ItemEx don't have the methods equals(Object) and hashCode(), so they cannot be used directly as keys in a HashMap. This is my assumption that you consider two Items with the same ID to be equal.
  • The two helper methods newLinkedHashMap just save some keystrokes in the method computeDeleteAndAdd. Without these methods you would have to say new LinkedHashMap<Long, Item>(...) instead of a simple newLinkedHashMap(...).


This solution loses the order of the lists...

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

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号