Как пройти через несколько списков, используя поток Java 8? - PullRequest
0 голосов
/ 28 августа 2018

У меня есть три списка,

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

Как я могу сделать это с помощью потокового API java-8?

Ответы [ 4 ]

0 голосов
/ 28 августа 2018

Нет необходимости в потоках - просто перенесите списки:

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]]

Очевидно, что это будет сложнее, если списки не имеют одинаковую длину.

0 голосов
/ 28 августа 2018

Работает, когда размеры списков одинаковы или различны:

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();
        });
0 голосов
/ 28 августа 2018

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]

В случае переменного размера списка итерация обхода безопасна, потому что я касаюсь только существующих индексов.

0 голосов
/ 28 августа 2018

Вы можете сделать (при условии, что все списки имеют одинаковый размер):

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)
...