【问题标题】:Java 8 stream one list to multiple listJava 8 将一个列表流式传输到多个列表
【发布时间】:2021-02-26 05:54:37
【问题描述】:

我需要根据某些属性将一个列表拆分为多个列表。

 List<Custom1> nums = new ArrayList<>();
        List<Custom2> cats = new ArrayList<>();
        List<Custom3> forms = new ArrayList<>();

        list.stream().forEach(custom -> {
            if (custom.getType().equalsIgnoreCase("N")) {
                Custom1 attr = new Custom1();
                attr.setAttrCd(custom.getCode());
                attr.setValue(Float.parseFloat(custom.getValue()));

                nums.add(attr);
            } else if (custom.getType().equalsIgnoreCase("C")) {
                Custom2 attr = new Custom2();
                attr.setAttrCd(custom.getCode());
                attr.setValue(Integer.parseInt(custom.getValue()));

                cats.add(attr);
            } else if (custom.getType().equalsIgnoreCase("F")) {
                Custom3 attr = new Custom3();
                attr.setAttrCd(custom.getCode());
                attr.setValue(custom.getValue());
                forms.add(attr);
            }
        });

使用流过滤器可以使相同的代码更好。

list.stream().filter(...).collect(toList())

但在我的情况下我需要迭代 3 次。 还有其他更好的方法吗?

【问题讨论】:

标签: java-8


【解决方案1】:

您应该尝试使用Collectors.partitioningBy() 并收集所需的列表作为地图中的值。您可以查看更多信息,例如这里 - https://stackoverflow.com/a/30110890/10479804

更新:正如 Nikolai 所说,partitioningBy() 只能用于根据 Predicate 函数拆分两个子集。

@user1578872,你应该考虑正确继承你的类:如果流中的所有类都有type字段和其他常见字段,我想你可以提取一些主要的抽象类。因此,您需要重构您的类,并将您的类型信息从类字段获取到类类型。

不过,我们假设您有:

public abstract class Custom {

    private String type;
    // other common fields
    // constructors etc.
}

以及扩展它的三个子类:Custom1Custom2Custom3。您可以将类型信息作为类名,例如NumCatForm。 因此,使用下一个代码,您可以根据对象类轻松地在 Sets 上划分整个流:

Map<Class, Set<Custom>> collect = list.stream()
        .collect(Collectors.groupingBy(Custom::getClass, toSet()));

非常简单的解决方案!

如果输入对象具有用于创建新的不同对象的其他字段,则会出现问题。如果您处理具有太多功能的对象集,我认为您不应该使用 Stream API。在这种情况下,或者您最好使用switch 构造在一个for-loop 中处理所有对象。另外你应该记住,在流中处理异常并不是那么容易,而且根本不是那么可读的解决方案。

如果您仍想使用 Streams,您基本上会将您的所有代码放入 lambda 表达式中,这些表达式必须传递给 Collectors.mapping

【讨论】:

  • 投反对票。 partitioningBy 只生成 2 个列表,而 OP 至少需要 3 个
  • 对不起,我的意思是Collectors.groupingBy
  • 如何在没有if条件的情况下转换成3个不同的对象?测量.stream().collect(Collectors.groupingBy(Custom::getType, Collectors.mapping(null, null)));
  • @user1578872,你的问题解决了吗?
  • 我需要转换为 3 diff 对象。所以,这个解决方案是不可能的。
【解决方案2】:

list.stream().filter(...).collect(toList()) 3 次没有问题。它的复杂性仍然是 O(n),而且你的代码更加简洁。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-27
    • 2014-08-15
    • 1970-01-01
    • 2017-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多