Как разделить поток на несколько потоков на основе определенных критериев? - PullRequest
3 голосов
/ 16 июня 2019

У меня есть список целых чисел, и я хочу вернуть подсписки целых чисел из этого списка, используя потоки Java 8, где мой подсписок содержит все положительные целые числа из исходного списка непосредственно перед тем, как он встретит отрицательное целое число

Например скажем, в моем списке есть элементы

[1 , 2 , 0 , -1 , 5 , 8 , 9 , -11 , 7 , 13 ]

тогда я должен вернуть подсписки, содержащие

  [1 , 2 , 0 ] [ 5 , 8 , 9 ] [7 , 13]  

Я попробовал следующий подход, но он не работает, ваше направление и вклад очень важны.

package Java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;

public class StreamsExamples {

    public static void main(String[] args) {
        ArrayList<Integer> arr = new ArrayList<Integer>();
        arr.add(1);
        arr.add(2);
        Integer[] al = new Integer[]{0,-1,5,8,9,-11,7,13};
        arr.addAll(Arrays.asList(al));
        arr.stream().collect(Collectors.groupingBy(Functionality::getPositiveList));
        // arr.stream().collect(Collectors.toList()).;
        //arr.stream().sorted().forEach(System.out::print);
    }


}

class Functionality{

    public List<List<Integer>> getPositiveList(List<Integer> list){
        List<List<Integer>> li = new ArrayList<List<Integer>>();
        List<Integer> a = new ArrayList<Integer>();
        for(int i=0;i<list.size();i++) {
            if(list.get(i)>=0) {
                a.add(list.get(i));
            }
            else if (list.get(i)<0) {
                li.add(a);
                a.clear();
            }
        }
        return li;

    }
}

Ответы [ 2 ]

5 голосов
/ 16 июня 2019

Это не так сложно, если вы думаете, что здесь немного по-другому: найдите индексы, где отрицательное значение, и просто сделайте subList между ними ... Есть некоторые причуды, связанные с IntStream.of(-1) (но Я дам вам понять, почему это так: попробуйте заменить его на более интуитивный IntStream.of(0) и посмотрите, что происходит). Таким образом, имея такой ввод:

ArrayList<Integer> arr = List.of(1, 2, 0, -1, 5, 8, 9, -11, 7, 13);

Вы сначала узнаете индексы:

int[] indexes = IntStream.concat(
IntStream.of(-1),
IntStream.concat(
      IntStream.range(0, arr.size())
               .filter(x -> arr.get(x) < 0),
      IntStream.of(arr.size())))
         .toArray();

System.out.println(Arrays.toString(indexes));

Это даст результат как: [-1, 3, 7, 10].

Таким образом, просто вычислите subList между ними:

IntStream.range(0, indexes.length - 1)
         .mapToObj(x -> arr.subList(indexes[x] + 1, indexes[x + 1]))
         .collect(Collectors.toList())
         .forEach(System.out::println);
2 голосов
/ 17 июня 2019

Это немного некрасиво, но это работает:

List<List<Integer>> lists = Arrays.stream(arr).boxed()
    .reduce(
        new ArrayList<>(),
        (l, i) -> {
            if (l.isEmpty() || i < 0) {
                l.add(new ArrayList<>());
            }
            if (i >= 0) {
                l.get(l.size() - 1).add(i);
            }
            return l;
        }, (a, b) -> {
            a.addAll(b);
            return a;
        });

Протестировано:

int [] arr = {1, 2, 0, -1, 5, 8, 9, -11, 7, 13};

List<List<Integer>> lists = Arrays.stream(arr).boxed().reduce(new ArrayList<>(),
        (l, i) -> {
            if (l.isEmpty() || i < 0) {
                l.add(new ArrayList<>());
            }
            if (i >= 0) {
                l.get(l.size() - 1).add(i);
            }
            return l;
        }, (a, b) -> {
            a.addAll(b);
            return a;
        });

System.out.println(lists);

Выход:

[[1, 2, 0], [5, 8, 9], [7, 13]]
...