【问题标题】:How to partition a collection into arbitrary sized partition如何将集合划分为任意大小的分区
【发布时间】:2015-01-10 21:33:09
【问题描述】:

我正在尝试使用 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,但开始时分区大小未知。

【问题讨论】:

  • 您遇到了什么问题?你已经描述了你想做什么,而不是你尝试做的困难。
  • 我没有看到用流做同样事情的方法。我不知道如何在流中将下一个元素标记为需要创建新的List&lt;String&gt;
  • 也许这会有所帮助:stackoverflow.com/questions/29095967/…

标签: java lambda java-8 java-stream


【解决方案1】:

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

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

它根据应用于一对相邻元素的谓词对输入元素进行分组。如果第二行与runStartPattern 匹配,我们不想将这些行分组。无论日志是否在运行中间开始,这都能正常工作。此外,此功能也适用于并行流。

【讨论】:

  • 顺便说一句,您是否将它添加到您的 API 以响应我的问题?
  • @CarlosBribiescas,不,我刚刚找到了你的问题。 groupRuns 功能在otheras well 中很有用。它与collapserunLengthsintervalMap 方法一起属于部分归约系列的一部分,这些方法将几个相邻元素合并为一个并在内部使用相同的机制。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-28
  • 1970-01-01
  • 2018-12-28
  • 1970-01-01
相关资源
最近更新 更多