首页 文章

从Java 8中的java.util.stream.Stream中检索List

提问于
浏览
390

我正在玩Java 8 lambdas来轻松过滤集合 . 但我没有找到一种简洁的方法来将结果检索为同一语句中的新列表 . 到目前为止,这是我最简洁的方法:

List<Long> sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
List<Long> targetLongList = new ArrayList<>();
sourceLongList.stream().filter(l -> l > 100).forEach(targetLongList::add);

网上的例子没有回答我的问题,因为他们停止而没有生成新的结果列表 . 必须有一个更简洁的方式 . 我原以为, Stream 类的方法为 toList()toSet() ,......

有没有办法可以直接由第三行分配变量 targetLongList

11 回答

  • 3

    如果您的流保持顺序,您正在做的事情可能是最简单的方式 - 否则您将不得不在 forEach 之前调用sequential() .

    [稍后编辑:调用sequential()的必要原因是,如果流是并行的,那么代码( forEach(targetLongList::add) )将会很有效 . 即使这样,它也不会达到预期的效果,因为 forEach 明确是不确定的 - 即使在顺序流中也不能保证元素处理的顺序 . 您必须使用 forEachOrdered 来确保正确的订购 . Stream API设计者的目的是在这种情况下使用收集器,如下所示 .

    另一种选择是

    targetLongList = sourceLongList.stream()
        .filter(l -> l > 100)
        .collect(Collectors.toList());
    
  • -2

    另一种方法是使用 Collectors.toCollection

    targetLongList = 
        sourceLongList.stream().
        filter(l -> l > 100).
        collect(Collectors.toList());
    
  • 547

    我喜欢使用一个util方法,它返回 ArrayList 的收集器,这就是我想要的 .

    我认为使用 Collectors.toCollection(ArrayList::new) 的解决方案对于这种常见操作来说有点太吵了 .

    例:

    ArrayList<Long> result = sourceLongList.stream()
        .filter(l -> l > 100)
        .collect(toArrayList());
    
    public static <T> Collector<T, ?, ArrayList<T>> toArrayList() {
        return Collectors.toCollection(ArrayList::new);
    }
    

    通过这个答案,我还想证明创建和使用自定义收集器是多么简单,这通常非常有用 .

  • 159

    如果您有一个基元数组,则可以使用Eclipse Collections中提供的基元集合 .

    LongList sourceLongList = LongLists.mutable.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
    LongList targetLongList = sourceLongList.select(l -> l > 100);
    

    如果您无法从 List 更改sourceLongList:

    List<Long> sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
    List<Long> targetLongList = 
        ListAdapter.adapt(sourceLongList).select(l -> l > 100, new ArrayList<>());
    

    如果你想使用 LongStream

    long[] sourceLongs = new long[]{1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L};
    LongList targetList = 
        LongStream.of(sourceLongs)
        .filter(l -> l > 100)
        .collect(LongArrayList::new, LongArrayList::add, LongArrayList::addAll);
    

    注意:我是Eclipse Collections的贡献者 .

  • 3

    更有效的方法(避免创建源列表和过滤器自动取消装箱):

    List<Long> targetLongList = LongStream.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L)
        .filter(l -> l > 100)
        .boxed()
        .collect(Collectors.toList());
    
  • 0
    collect(Collectors.toList());
    

    这是您可以用来将任何Stream转换为List的调用 .

  • 0

    如果你没有't mind using 3rd party libraries, AOL' s cyclops-react lib(披露我是贡献者)有所有JDK Collection类型的扩展名,包括List . ListX接口扩展了java.util.List并添加了大量有用的运算符,包括filter .

    你可以简单地写 -

    ListX<Long> sourceLongList = ListX.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
    ListX<Long> targetLongList = sourceLongList.filter(l -> l > 100);
    

    ListX也可以从现有List创建(通过ListX.fromIterable)

  • 9

    如果某人(像我一样)在寻找处理Objects而不是原始类型的方法,那么使用mapToObj()

    String ss = "An alternative way is to insert the following VM option before "
            + "the -vmargs option in the Eclipse shortcut properties(edit the "
            + "field Target inside the Shortcut tab):";
    
    List<Character> ll = ss
                            .chars()
                            .mapToObj(c -> new Character((char) c))
                            .collect(Collectors.toList());
    
    System.out.println("List type: " + ll.getClass());
    System.out.println("Elem type: " + ll.get(0).getClass());
    ll.stream().limit(50).forEach(System.out::print);
    

    打印:

    List type: class java.util.ArrayList
    Elem type: class java.lang.Character
    An alternative way is to insert the following VM o
    
  • 1

    这是代码AbacusUtil

    LongStream.of(1, 10, 50, 80, 100, 120, 133, 333).filter(e -> e > 100).toList();
    

    披露:我是AbacusUtil的开发人员 .

  • 0
    String joined = 
                    Stream.of(isRead?"read":"", isFlagged?"flagged":"", isActionRequired?"action":"", isHide?"hide":"")
                          .filter(s -> s != null && !s.isEmpty())
                          .collect(Collectors.joining(","));
    
  • 3

    如果你不使用 parallel() ,这将有效

    List<Long> sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
    
    List<Long> targetLongList =  new ArrayList<Long>();
    
    sourceLongList.stream().peek(i->targetLongList.add(i)).collect(Collectors.toList());
    

相关问题