我正在努力研究Java 8中的可选问题。我编写了一个非常简单的程序,由一个类和main()
方法组成。
我希望输出数据为[aaa, DDD, ccc]
。但是,我得到了[aaa, bbb, ccc]
。但如果更改为s = new TestClass("DDD")
到评论的那一行,我就会得到我想要的内容。
那么map()
如何运作?它只能通过编辑来映射对象吗?如果我创建一个新实例并将其返回,为什么它不能正常工作?
类:
public class TestClass {
String str;
public TestClass(String str) {
this.str = str;
}
@Override
public String toString() {
return str;
}
}
main()方法:
public static void main(String[] args) {
List<TestClass> list = new ArrayList<TestClass>();
list.add( new TestClass("aaa") );
list.add( new TestClass("bbb") );
list.add( new TestClass("ccc") );
list.stream()
.filter( s -> s.str.equals("ccc") || s.str.equals("bbb") )
.findFirst()
.map( s -> {
// s.str = "DDD"; this works just fine
s = new TestClass("DDD");
return s;
} );
System.out.println(list);
}
答案 0 :(得分:2)
使用s.str = "DDD"
,您修改或变更列表中的TestClass
实例,将其str
字段设置为值{{ 1}}。
使用DDD
,您无法触及列表中的实例。变量s = new TestClass("DDD")
是该lambda块的局部变量。为其分配新的对象引用不会更改它先前指向的对象的s
字段。
通常,使用地图,您必须收集它或对结果执行某些操作。但是在这里你没有对映射结果做任何事情。
答案 1 :(得分:2)
请将您的代码更改为:
Optional<Object> result = list.stream()
.filter( s -> s.str.equals("ccc") || s.str.equals("bbb") )
.findFirst()
.map( s -> {
// s.str = "DDD"; this works just fine
s = new TestClass("DDD");
return s;
} );
System.out.println(result);
再次运行 - 它应该给你一些提示。
请注意,您根本不使用版本中的结果,在这种情况下修改源列表不是最佳习惯(可能存在多线程问题)
答案 2 :(得分:2)
您正在
方法中指定新对象。您的新引用仅在方法范围内有效,但一旦返回,引用将指向其原始实例。
在java
中,这是预期的行为。
E.g:
String s = "foo";
changeString(s);
print(s); // prints "foo"
,其中
void changeString(String s) {
s = "bar";
}
没有人禁止你更改对象属性,就像使用s.str = "DDD"
一样(当然,除非你的对象是不可变的)。
在您的特定情况下,您没有对map
lambda结果执行任何操作,因此您的更改将丢失。
实际上map
在你的情况下是无用的,即使你只是在s.str = "DDD"
内进行forEach
。
<强>但
即可。因为你只处理一个甚至可能不存在的结果(可选),所以你应该使用...findFirst().ifPresent(s -> s.str = "DDD" );
只有当您需要将对象转换为其他类型以进行进一步处理时,才应使用map
。
答案 3 :(得分:1)
'map'方法用于将每个元素映射到其对应的结果。如果要更改列表中的一个元素,则需要将结果收集到新的列表中。使用.collect()方法。
unsigned char
结果是:
aaa
DDD
CCC
整理流:
List<TestClass> list = new ArrayList<TestClass>();
list.add( new TestClass("aaa") );
list.add( new TestClass("bbb") );
list.add( new TestClass("ccc") );
List<TestClass> result = list.stream()
.map( s -> {
if (s.toString().equals("bbb")) {
s = new TestClass("DDD");
}
return s;
}).collect(Collectors.toList());
for(TestClass t : result){
System.out.println(t);
}