【问题标题】:How to traverse multiple list using Java 8 stream?如何使用 Java 8 流遍历多个列表?
【发布时间】:2018-08-28 13:51:28
【问题描述】:

我有三个列表,

List<Double> list1= new ArrayList(List.of(1, 1.5));
List<Double> list2= new ArrayList(List.of(30, 25));
List<Double> list3= new ArrayList(List.of(30, 25));

我想同时遍历每一个,然后打印

1    30  30
1.5  25  25

如何使用 java-8 流 API 做到这一点?

【问题讨论】:

  • 提醒为什么for comprehensions 很棒。 :)

标签: java list java-8 java-stream


【解决方案1】:

您可以这样做(假设所有列表的大小相同):

IntStream.range(0, list1.size())
         .forEach(x -> Syso(list1.get(x) + " " + list2.get(x) + " " + list3.get(x)))

但是这里并没有真正的好处,只是使用一个普通的 for 循环。

顺便说一句,不要用new ArrayList(List.of(30, 25)); 包装这些,这就足够了:

 List<Double> list1 = List.of(1D, 1.5D)

【讨论】:

    【解决方案2】:

    List.of(..) 是一个静态工厂,它本身返回一个List,无需将其包装到ArrayList::new 构造函数中。

    这里是您可能需要的代码,但是,不要低估for-loop 的强大功能:

    // Here you need to get the max of all the List sizes to traverse all Lists
    int maxSize = Math.max(list1.size(), Math.max(list2.size(), list3.size()));      
    
    IntStream.range(0, maxSize)                                    // Iterate 0 .. minSize-1
             .mapToObj(i -> Stream.of(list1, list2, list3)         // Map each index
                                  .filter(list -> i < list.size()) // Secure the existing index
                                  .map(list -> list.get(i))        // Get the item
                                  .collect(Collectors.toList()))   // Collect to List
                                  .forEach(System.out::println);   // And iterate (print)
    

    输出:

    [1, 30, 30]
    [1.5, 25, 25]
    

    在可变列表大小的情况下,遍历迭代是安全的,因为我只触及现有索引。

    【讨论】:

    • 您可以首先使用Math.min 完全删除filter。收集也没有增加真正的好处。因为您可以使用 .forEach 遍历流
    【解决方案3】:

    不需要流 - 只需转置列表:

    private static class Transpose<T> extends AbstractList<List<T>> implements List<List<T>> {
        private final List<T> [] lists;
        public Transpose(List<T>... lists) {
            this.lists = lists;
        }
    
        private class Column extends AbstractList<T> implements List<T> {
            private final int column;
    
            public Column(int column) {
                this.column = column;
            }
    
            @Override
            public T get(int row) {
                return lists[row].get(column);
            }
    
            @Override
            public int size() {
                return lists.length;
            }
        }
        @Override
        public List<T> get(int column) {
            return new Column(column);
        }
    
        @Override
        public int size() {
            return lists[0].size();
        }
    }
    
    private void test() {
        List<Double> list1= Arrays.asList(1.0, 1.5);
        List<Double> list2= Arrays.asList(30.0, 25.0);
        List<Double> list3= Arrays.asList(30.0, 25.0);
    
        List<List<Double>> matrix = new Transpose(list1, list2, list3);
        System.out.println(matrix);
    }
    

    打印:

    [[1.0, 30.0, 30.0], [1.5, 25.0, 25.0]]

    如果列表长度不同,这显然会更困难。

    【讨论】:

      【解决方案4】:

      这适用于列表大小相同或不同的情况:

      List<Double> list1 = List.of(1D, 1.5D);
      List<Double> list2 = List.of(30D, 25D);
      List<Double> list3 = List.of(30D, 25D);
      Stream<List<Double>> listStream = Stream.of(list1, list2, list3);
      
      int maxSize = listStream.mapToInt(List::size).max().orElse(0);
      
      IntStream.range(0, maxSize)
              .forEach(index -> {
                  listStream
                          .filter(list -> list.size() > index)
                          .forEach(list -> System.out.print(list.get(index) + " "));
                  System.out.println();
              });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-11
        • 1970-01-01
        • 1970-01-01
        • 2012-05-26
        • 1970-01-01
        相关资源
        最近更新 更多