given I have a list of items that all inherit from the same base class:
class Item {
protected String name;
public Item(String name) {
this.name = name;
}
getName() {
return name;
}
}
class ItemA extends Item {...}
class ItemB extends Item {...}
List<Item> itemList = Arrays.asList(new ItemA("itemA"), new ItemB("itemB"));
In my case I have no control over how these classes are implemented but I need to separate the list into two different lists containing the name of the respective element.
Here is the first try at a solution that contains lots of if
and instanceof
statements:
List<String> itemAList = new ArrayList<>();
List<String> itemBList = new ArrayList<>();
itemList.forEach(item -> {
if(item instanceof ItemA) {
itemAList.add(item.getName());
}
else if(item instanceof ItemB) {
itemBList.add(item.getName());
}
});
So this works but I gave it some thought on how to avoid the if
statements. Since I'm using Java 8 I can do this:
List<String> itemAList = itemList.stream()
.filter(ItemA.class::isInstance)
.map(item -> item.getName())
.collect(Collectors.toList());
List<String> itemBList = itemList.stream()
.filter(ItemB.class::isInstance)
.map(item -> item.getName())
.collect(Collectors.toList());
This works as well but it means I have to process the list two times.
As I said I have no bearing on the implementation of the Item
classes so what would be the best way to implement such a behavior?
Greetings
[edit:] Thank you for all the responses. I've learned something new today.
You can group the content based on the class of the elements :
Map<Class, List<String>> grouped = itemList.stream()
.collect(Collectors.groupingBy(Item::getClass,
Collectors.mapping(Item::getName, Collectors.toList())));
and access it as:
List<String> itemAList = grouped.get(ItemA.class);
As you said you have different instances you have no control over, so you can't really be sure that only ItemA
and ItemB
occur in the list.
You're better of using a map, which has the name as the key and a List
of Item
s as values:
Map<String, List<Item>> map = itemList.stream()
.collect(Collectors.groupingBy(Item::getName, Function.identity()));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With