如何将集合分区为任意大小的分区

时间:2014-11-13 16:43:17

标签: java lambda java-8 java-stream

我正在尝试使用Java 8 Lambda表达式和流来解析一些日志。我有一个运行后运行的巨型日志文件。我想将它拆分为单独的集合,每次运行一个。我不知道日志中有多少次运行。为了锻炼我非常弱的lambda表情肌肉,我想在列表中一次性地完成它。

这是我目前的实施:

    List<String> lines = readLines(fileDirectory);

    Pattern runStartPattern = Pattern.compile("INFO: \\d\\d:\\d\\d:\\d\\d: Starting");

    LinkedList<List<String>> testRuns = new LinkedList<>();

    List<String> currentTestRun = new LinkedList<>(); // In case log starts in middle of run
    testRuns.add(currentTestRun);

    for(String line:lines){
        if(runStartPattern.matcher(line).find()){
            currentTestRun = new ArrayList<>();
            testRuns.add(currentTestRun);
        }
        currentTestRun.add(line);
    }
    if(testRuns.getFirst().size()==0){ // In case log starts at a run
        testRuns.removeFirst();
    }

基本上类似于TomekRekawek的解决方案here,但开头的分区大小未知。

1 个答案:

答案 0 :(得分:1)

在Stream API中没有标准方法可以轻松实现这一点,但我的StreamEx库有一个groupRuns方法可以很容易地解决这个问题:

List<List<String>> testLines = StreamEx.of(lines)
        .groupRuns((a, b) -> !runStartPattern.matcher(b).find())
        .toList();

它根据应用于相邻元素对的某个谓词对输入元素进行分组。如果第二行与runStartPattern匹配,我们不希望对这些行进行分组。无论日志是否在运行过程中启动,这都可以正常工作。此功能也适用于并行流。