kacpr
kacpr

Reputation: 392

how to search an arraylist for duplicate objects (determined by one field) and merge them

I have a class called PriceList

class PriceList {
    Integer priceListID;
    ...
}

and I have extended it in another class to accommodate some user functionality

class PriceListManager extends PriceList{
    boolean user;
    boolean manager;
}

One user can have an ArrayList of PriceListManager objects, that can contain duplicates (same PriceListID), so I would like to find these duplicates and compare they're fields to create one entry eg.:

{ PriceListID = 5; user = false; manager = true; 
   PriceListID = 5; user = true; manager = false; }

should become

PriceListID = 5; user = true; manager = true;

What would be the best approach to that? I already have equals methods for both classes, PriceList compares two objects by just checking their IDs while PriceListManagers does that AND checks if both boolean fields are the same.

edit: I need to find any objects with same ID, so I can merge their attributes and leave only one object.

Upvotes: 3

Views: 954

Answers (5)

wallenborn
wallenborn

Reputation: 4273

You have implemented equals and hashCode on PriceListManager to use all fields, but for this particular purpose you need them to match on priceListID alone, right? Maybe you want to give this construction one more thought: what is your entity here? does priceListID alone already determine a priceListManager? In any case, if you want a local solution to this, i'd use a Map and then do something like this:

Map<Integer, PriceListManager> lookup = new HashMap<Integer, PriceListManager>();
for (PriceListManager item: priceListManagers) {
  PriceListManager manager = lookup.get(item.getPriceListID());
  if (manager == null) {
    manager = new PriceListManager();
    manager.setPriceListID(item.getPriceListID());
    manager.setUser(false);
    manager.setManager(false);
    lookup.put(manager.getPriceListID(), manager);
  }
  manager.setUser(manager.getUser() || item.getUser());
  manager.setManager(manager.getManager() || item.getManager());
}

Upvotes: 1

Tom Mac
Tom Mac

Reputation: 9853

How about something like this:

    Map<Integer, PriceListManager> map = new HashMap<Integer, PriceListManager>();

    for (PriceListManager manager : yourArrayList) {

        if (!map.contains(manager.getPriceListID())) {
            map.put(manager.getPriceListID(), manager);
        }

        if (manager.isUser()) {
            map.get(manager.getPriceListID()).setIsUser(true);
        }

        if (manager.isManager()) {
            map.get(manager.getPriceListID()).setIsManager(true);
        }
    }

    List<PriceListManager> newList = new ArrayList<PriceListManager>();
    newList.addAll(map.values());

    // Do stuff with newList....

Upvotes: 2

siledh
siledh

Reputation: 3378

Go through the original list, and if you find an object that was already there, then merge those two into one:

Collection<? extends PriceList> convertToMergedList(Iterable<? extends PriceList> listWithDuplicated) {
    Map<Integer, PriceList> idToMergedObject = new LinkedHashMap<>();
    for(PriceList price : listWithDuplicated) {
        if (idToMergedObject.get(price.piceListId) == null) {
            idToMergedObject.put(price.piceListId, price);
        } else {
            PriceList priceSoFar = idToMergedObject.get(price.piceListId);
            PriceList priceMerged = merge(priceSoFar, price);
            idToMergedObject.put(price.piceListId, priceMerged);
        }
    }

    return idToMergedObject.values();
}

PriceList merge(PriceList price1, PriceList price2) {
   // merging logic
}

I use LinkedHashMap, so that the original order of elements is preserved.

Upvotes: 0

Prashant Thakkar
Prashant Thakkar

Reputation: 1403

You can try to iterate through list and convert it into HashMap, where priceListID will be key and PriceListManager as value. While iterating over the ArrayList, check if hashmap whether value for particular priceListID exists :
1. if yes compare the same with current one
2. if not equal update as per your logic.
3. If equal no need to update and
4. if doesn't exists add it to hashmap

I hope this helps.

Upvotes: 1

Mathias G.
Mathias G.

Reputation: 5085

If you don't want duplicates. Isn't it a good idea to work with a Set instead of an ArrayList? Uniqueness is guaranteed in a Set.

You gain performance and have to implement less code since you don't have to do the duplicate check afterwards...

Upvotes: 0

Related Questions