我有一个更新String对象的循环:
String result = "";
for (SomeObject obj: someObjectList) {
result = someMetohd(obj, result);
}
someMethod的实现是无关紧要的:
private String someMethod(SomeObject obj, String result) {
result = result.concat(obj.toString());
return result;
}
我想使用Stream而不是循环。如何用Stream实现它?
答案 0 :(得分:1)
final StringBuilder resultBuilder = new StringBuilder();
someObjectList.stream().map(SomeObject::toString).forEach(resultBuilder::append);
final String result = resultBuilder.toString();
要了解有关Streams的更多信息,您可以查看此页面:http://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/,我认为这非常有用。
答案 1 :(得分:1)
@SuppressWarnings("OptionalGetWithoutIsPresent")
String result = Stream.concat(Stream.of(""), someObjectList.stream())
.reduce(this::someMethod)
.get();
someMethod
应该与文档中指定的关联,但这仅对并行流很重要,而您的代码是明确顺序的result
时,您可以将其视为流的第一个元素,然后使用reduce
方法,该方法将始终合并前两个元素 - 当前结果和下一个元素result
必须是someMethod
String result
和SomeObject
元素,因此需要更改someMethod
的签名以接受两个{{ 1}} s(并在方法中进行强制转换):Object
。这是该解决方案中最丑陋的部分。 private String someMethod(Object result, Object obj)
result
this::someMethod
结果,因为流始终至少包含一个元素,因此只需调用Optional
答案 2 :(得分:1)
尽管您在此处尝试实现的功能等同可以通过流实现,但值得提醒您的是,功能和迭代思维方式不一定兼容。
一般情况下,您自己会考虑每个元素,除非您使用像reduce这样的特殊功能,否则您无法看到其他元素。
这里有一些符合你要求的东西:
final List<Object> objectList = Arrays.asList("a", "b", "c", "d");
String concatString = objectList.stream()
.map(e -> e.toString())
.reduce((result, element) -> result.concat(e))
.get();
Map将整个流转换为列表,但是在每个元素上分别调用toString函数。减少更复杂。它可以被描述为积累。它在结果和当前元素之间执行一个函数。在这种情况下,它接受第一个元素,并将其连接到第二个元素。然后它采用第一个/第二个连接,并将相同的函数应用于第三个。等等。
您可以直接传递方法,而不是处理lambdas,以便稍微收紧一下代码:
String result = objectList.stream()
.map(Object::toString)
.reduce(String::concat)
.get();