Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用java流对由空行分隔的字符串行进行分组_Java_Functional Programming - Fatal编程技术网

如何使用java流对由空行分隔的字符串行进行分组

如何使用java流对由空行分隔的字符串行进行分组,java,functional-programming,Java,Functional Programming,我有以下输入,我希望使用空行作为逻辑分隔符对它们进行分组。 输入数据类型: 列表 预期产出: 类型:列表 虽然使用命令式编程很简单,但我正在寻找一种在Java中使用函数式编程的解决方案。您没有说您使用的是什么Java版本,但这应该在Java8+中工作。如果使用带有3个参数的函数,则stream上的reduce函数可以为您提供所需的内容。在本例中,使用带有字符串列表的列表、获取当前结果的lambda函数和单个字符串。当它看到一个空行时,它确实完成了添加一个新列表的所有工作。最后,一个组合器解释了如

我有以下输入,我希望使用空行作为逻辑分隔符对它们进行分组。 输入数据类型:
列表

预期产出: 类型:列表


虽然使用命令式编程很简单,但我正在寻找一种在Java中使用函数式编程的解决方案。

您没有说您使用的是什么Java版本,但这应该在Java8+中工作。如果使用带有3个参数的函数,则
stream
上的
reduce
函数可以为您提供所需的内容。在本例中,使用带有字符串列表的列表、获取当前结果的lambda函数和单个字符串。当它看到一个空行时,它确实完成了添加一个新列表的所有工作。最后,一个组合器解释了如何组合两个列表,但实际上只是为了帮助编译器理解正在发生的事情。在这种情况下,它只会返回一个空列表

String input=“line1\n”+
“第2行\n”+
“第3行\n”+
“\n”+
“第4行\n”+
“第5行\n”+
“第6行\n”+
“\n”+
“第7行\n”+
“第8行”;
List strings=Arrays.stream(input.split(“\n”)).collect(Collectors.toList());
列表初始值=新的ArrayList();
add(newarraylist());
列表结果=strings.stream().reduce(初始,(小计,元素)->{
if(element.trim().isEmpty()){
小计.添加(新的ArrayList());
}否则{
subtotal.get(subtotal.size()-1).add(元素);
}
返回小计;
},(列表1,列表2)->emptyList());

我得到结果[[line1,line2,line3],[line4,line5,line6],[line7,line8]]的
列表的输出,我相信这就是您想要的结果。

可以通过使用已知的空字符串作为分隔符将列表拆分为子列表来完成:

List<String> data = Arrays.asList("a", "b", "c", "", "d", "", "e", "f");

int[] indexes = 
                Stream.of(
                  IntStream.of(-1), 
                  IntStream.range(0, data.size()).filter(i -> data.get(i).isEmpty()), 
                  IntStream.of(data.size())
                ) 
                .flatMapToInt(ix -> ix)
                .toArray();
List<List<String>> subSets = 
          IntStream.range(0, indexes.length - 1)
                   .mapToObj(i -> data.subList(indexes[i] + 1, indexes[i + 1]))
                   .collect(Collectors.toList());
subSets.forEach(System.out::println);
或者可以通过重新连接和重新拆分输入数据来实现(如果输入是
列表
):

List data=Arrays.asList(“a”、“b”、“c”、“d”、“e”、“f”);
数组.stream(
data.stream()
.collect(收集器.joining(“\n”)).split(“\n{2}”)//按双“空行”拆分
)
.map->Arrays.stream(s.split(“\n”).collect(Collectors.toList())
.collect(收集器.toList())
.forEach(System.out::println);

输出与上面相同。

您的输入是单个字符串还是字符串列表或文本文件或其他内容?输入是列表您的第二种方法容易出错。假设那些
##
####
不会出现在行中。是的,这种假设是基于测试数据做出的。不过,我在更新中将这些自定义分隔符替换为
\n
。很抱歉,它似乎不起作用。您有打印件吗?@Mox您需要更改什么?我可以为其他人更新答案。我已编辑了你的答案。不太确定你是否能看到它
{{line1, line2, line3}, {line4, line5, line6}, {line7, line8}}
List<String> data = Arrays.asList("a", "b", "c", "", "d", "", "e", "f");

int[] indexes = 
                Stream.of(
                  IntStream.of(-1), 
                  IntStream.range(0, data.size()).filter(i -> data.get(i).isEmpty()), 
                  IntStream.of(data.size())
                ) 
                .flatMapToInt(ix -> ix)
                .toArray();
List<List<String>> subSets = 
          IntStream.range(0, indexes.length - 1)
                   .mapToObj(i -> data.subList(indexes[i] + 1, indexes[i + 1]))
                   .collect(Collectors.toList());
subSets.forEach(System.out::println);
[a, b, c]
[d]
[e, f]
List<String> data = Arrays.asList("a", "b", "c", "", "d", "", "e", "f");

Arrays.stream(
    data.stream()
    .collect(Collectors.joining("\n")).split("\n{2}") // split by double 'empty lines'
)
.map(s -> Arrays.stream(s.split("\n")).collect(Collectors.toList()))
.collect(Collectors.toList())
.forEach(System.out::println);