Java 8:groupby with Comparator

时间:2018-01-22 06:39:37

标签: java java-8

我有一个int列表,例如(1,2,4,6,7,8)。 我想知道Java 8中是否存在创建列表列表。

如果

(x,y)->x+1=y 

它应该在同一个列表中。

在此示例中,输出应为:

(1,2), (4), (6,7,8)

我可以这样写:

public static List<List<int>> group(List<int> list, GroupFunctionByOrder groupFunction) {

    List<List<int>> result = new ArrayList<>();

    for (int l : list) {

        boolean groupFound = false;
        for (List<int> group : result) {
            if (groupFunction.sameGroup(l, group.get(group.size()-1))) {
                group.add(l);
                groupFound = true;
                break;
            }
        }

        if (! groupFound) {
            List<int> newGroup =  new ArrayList<>();
            newGroup.add(l);
            result.add(newGroup);
        }
    }

    return result;
}

public class GroupFunctionByOrder {
    public boolean sameGroup(int l1, int  l2){
        return l1+1 == l2;
    }
}

4 个答案:

答案 0 :(得分:5)

您可以使用StreamEx库执行此操作:

List<List<Integer>> grouped = StreamEx.of(1,2,4,6,7,8)
        .groupRuns((x, y) -> x + 1 == y)
        .toList();

答案 1 :(得分:1)

不,这可能是不可能的。

由于流的非常本质 - 您无法深入了解下一步处理的值,也无法从流中的任意点提取值 - 做这样的事情是从Java流的角度来看是不可行的。

首先,您无法在流上下文中访问BiFunctionBiPredicate。如果可以的话,那么你就有机会根据先前的顺序将值分开。

答案 2 :(得分:1)

java7中有效的方法也可以在java8中运行:)

import java.util.*;


public class Main {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1,2,4,6,7,8);
        List<List<Integer>> result = new ArrayList<>();

        List<Integer> prev = new ArrayList<>();
        prev.add(list.get(0));

        //iterate over the list
        for (int i = 1 ; i < list.size(); i++){
            // Add to list if does not satisfy condition
            if (list.get(i) != list.get(i-1) +1){
                result.add(prev);
                prev = new ArrayList();
            }
            prev.add(list.get(i));
        }

        result.add(prev);

        // print result
        for(List<Integer> p : result) {
            Object[] arr = p.toArray();
            System.out.print(Arrays.deepToString(arr));
        }


    }
}

答案 3 :(得分:0)

我不知道Java 8中的直接方式,但这是另一种解决方案:

List<Integer> list = List.of(1, 2, 4, 6, 7, 8);

List<List<Integer>> result = new ArrayList<>();
int start = 0, i = 1, size = list.size();
while (i < size) {
    while (i < size && list.get(i - 1) + 1 == list.get(i)) i++;
    result.add(list.subList(start, i));
    start = i++;
}

System.out.println(result); // [[1, 2], [4], [6, 7, 8]]

这使用List.subList,它返回原始列表支持的子列表视图。这段代码的想法是移动索引直到条件被破坏,将子列表添加到结果中,然后从那一点开始。