Java 8 按类分离列表元素

标签 java lambda java-8 java-stream

假设我有一个全部继承自同一基类的项目列表:

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

在我的例子中,我无法控制这些类的实现方式,但我需要将列表分成两个不同的列表,其中包含相应元素的名称。

这是第一次尝试包含大量 ifinstanceof 语句的解决方案:

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

所以这行得通,但我考虑了如何避免 if 语句。因为我使用的是 Java 8,所以我可以这样做:

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

这也有效,但这意味着我必须处理列表两次。

正如我所说,我与 Item 类的实现无关,那么实现这种行为的最佳方式是什么?

问候

[edit:] 感谢您的所有回复。我今天学到了一些新东西。

最佳答案

您可以根据元素的类别对内容进行分组:

Map<Class, List<String>> grouped = itemList.stream()
        .collect(Collectors.groupingBy(Item::getClass,
                Collectors.mapping(Item::getName, Collectors.toList())));

并将其访问为:

List<String> itemAList = grouped.get(ItemA.class);

关于Java 8 按类分离列表元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55301160/

相关文章:

python - Pandas 中基于行计算的有效方法

java - 在流中创建新对象并使用 setter

java - 如何使用 Java 在 Mongo 中添加和删除数组中的元素?

java - 如何在 ArchUnit 规则中排除某个类?

c# - 从列表中删除所有内容,其中每行不包含另一个列表中的任何项目

java - 带退出的 TestNg 控制台应用程序

java - 服务器JRE和客户端JRE的区别

java - 未连接调试器时 jvmti 的性能影响?

java - 没有已知的包错误。安卓5.0

c# - 运行时的 Expression.Lambda 和查询生成,最简单的 "Where"示例