尝试编写一个简单的程序,用于打印 Java8 中输入数组中的唯一单词。例如,如果输入是
String[] input = {"This", "is", "This", "not"};
程序应输出[T, h, i, s, n, o, t]
,元素的顺序应遵循与输入中出现的相同的模式。我的方法是split
输入,然后是map
,distinct
,最后是collect
toList。但是下面的代码是打印流而不是单词列表,我缺少什么?。例如
String[] input = {"This", "is", "This", "not"};
System.out.println(Arrays.stream(input)
.map(word -> word.split(""))
.map(Arrays::stream)
.distinct()
.collect(toList()));
当前输出
[java.util.stream.ReferencePipeline$Head@548c4f57, java.util.stream.ReferencePipeline$Head@1218025c, java.util.stream.ReferencePipeline$Head@816f27d, java.util.stream.ReferencePipeline$Head@87aac27]
我很想知道Java8中是否还有其他方法可以实现相同的目标。
答案 0 :(得分:5)
您需要使用flatMap来映射流的内容。正如您注意到Arrays::stream
生成单独的流,您想要的是将所有这些流展平为单个流E.g。
System.out.println(Stream.of(input)
.map(w -> w.split(""))
.flatMap(Arrays::stream)
.distinct()
.collect(Collectors.toList()));
输出
[T, h, i, s, n, o, t]
答案 1 :(得分:2)
补充@ sol4me的另一个解决方案答案:
System.out.println(Stream.of(input).flatMapToInt(CharSequence::chars)
.distinct().mapToObj(c -> Character.valueOf((char) c))
.collect(Collectors.toList()));
可能会以更有效的方式撰写。
不幸的是,JDK没有定义CharStream
......
答案 2 :(得分:2)
Java in Action 8:对使用平面地图有很好的解释,我重申先前发布的解决方案,并按书进行解释。
String[] input = {"This", "is", "This", "not"};
map函数返回一个流,该流包括将给定函数应用于此流的元素的结果。
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
List<Stream<String>> steramsOfStream = Arrays.stream(input)
.map(word -> word.split(""))
.map(Arrays::stream)
.distinct().collect(Collectors.toList());
steramsOfStream.forEach(a -> {
a.forEach(System.out::print);
System.out.print("\n");
});
这将产生以下输出
输出: [这是,这不是]
flat map返回一个流,该流由以下结果组成:“将流中的每个元素替换为通过将提供的映射函数应用于每个元素而生成的映射流的内容。
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
List<String> listOfStringss = Arrays.stream(input)
.map(word -> word.split(""))
.flatMap(Arrays::stream)
.distinct().collect(Collectors.toList());
System.out.println(listOfStringss);
产生输出: [T,h,i,s,n,o,t] [] 2