So I’m wondering what is the best solution to the following problem:
I have a list of items (a custom class) in a java collection ex
List<Item> itemList = ... item1,item2,item3 etc
Each item in the collection however has a corresponding logical pair also in the collection (so the pair’s are not necessarily following each other by index in the collection)
I have a helper method like
Item calculateCorrectItem(Item item1, Item item2)
which can return the correct one of a pair based on some business logic (the details of that is not relevant)
I would like to replace an item and its pair in the collection, with the result of the method above – so that every 2 elements of a pair in the collection are replaced with the calculated one based on those two.
Some details:
We can assume that every element has one and only one pair.
Each item has the pair’s ID as a property, like
public class Item { private String id; private String pairId; the equal method is true when the ID of two items are the same. ...getters,setters }
Also, the references in the collection which i want to filter are also existing in a global cache, where every Item can be easily retrieved from, like
globalCache.getItemById(String id)
So an actual pair reference can be easily retrieved if the ID of the pair is known.
What could be an elegant solution (maybe by utilizing the Stream IPA)? In the end, the only expectation is that the collection contains one Item of each pair, the ordering doesn’t matter.
Advertisement
Answer
With streams, you would have to do this using indexed access:
List<Item> calculated = IntStream.range(0, itemList.size() / 2) .mapToObj(i -> calculateCorrectItem(itemList.get(2*i+0), itemList.get(2*i+1)) .collect(toList());
If you want to merge items based on their IDs, you can group the items by their ID:
itemList.stream() .collect(groupingBy(Item::getId)) // Yields a Map<IdType, List<Item>> .values() // Yields a Collection<List<Item>>, where each List<Item> contains items with the same id. .stream() .map(is -> /* invoke calculateCorrectItem, handling 1, 2 or more items in the list */) .collect(...)