Java Optional.map-它到底是如何工作的?

Java Optional.map-它到底是如何工作的?,java,optional,Java,Optional,我试图探讨Java8中的可选问题。我编写了一个非常简单的程序,由一个类和main()方法组成 我希望输出数据是[aaa、DDD、ccc]。然而,我得到了[aaa、bbb、ccc]。但是如果将s=newtestclass(“DDD”)行更改为注释行,我就得到了我想要的 那么map()是如何工作的呢?它只能通过编辑对象来映射对象吗?如果我创建一个新实例并返回它,为什么它不能正常工作 类别: public class TestClass { String str; public Te

我试图探讨Java8中的可选问题。我编写了一个非常简单的程序,由一个类和
main()
方法组成

我希望输出数据是
[aaa、DDD、ccc]
。然而,我得到了
[aaa、bbb、ccc]
。但是如果将
s=newtestclass(“DDD”)
行更改为注释行,我就得到了我想要的

那么
map()
是如何工作的呢?它只能通过编辑对象来映射对象吗?如果我创建一个新实例并返回它,为什么它不能正常工作

类别:

public class TestClass {
    String str;

    public TestClass(String str) {
        this.str = str;
    }

    @Override
    public String toString() {
        return str;
    }
}
main()方法:

publicstaticvoidmain(字符串[]args){
列表=新的ArrayList();
添加(新的测试类(“aaa”);
添加(新的测试类(“bbb”);
添加(新的测试类(“ccc”);
list.stream()
.filter(s->s.str.equals(“ccc”)| | s.str.equals(“bbb”))
.findFirst()
.map(s->{
//s.str=“DDD”这很好用
s=新的测试类(“DDD”);
返回s;
} );
系统输出打印项次(列表);
}
使用
s.str=“DDD”
您正在修改或变异列表中的
TestClass
实例,将其
str
字段设置为
DDD

使用
s=newtestclass(“DDD”)
,您不会接触列表中的实例。变量
s
是该lambda块的局部变量。将新对象引用指定给它不会更改它先前指向的对象的
str
字段

通常,有了地图,你必须收集它或对结果做些什么。但是这里您没有对映射结果做任何操作。

使用
s.str=“DDD”
您正在修改或变异列表中的
TestClass
实例,将其
str
字段设置为值
DDD

使用
s=newtestclass(“DDD”)
,您不会接触列表中的实例。变量
s
是该lambda块的局部变量。将新对象引用指定给它不会更改它先前指向的对象的
str
字段


通常,有了地图,你必须收集它或对结果做些什么。但在这里,您没有对映射结果执行任何操作。

请将代码更改为:

        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); 
Optional result=list.stream()
.filter(s->s.str.equals(“ccc”)| | s.str.equals(“bbb”))
.findFirst()
.map(s->{
//s.str=“DDD”这很好用
s=新的测试类(“DDD”);
返回s;
} );
系统输出打印项次(结果);
然后再跑一次-它会给你一些提示


请注意,您的版本中根本不使用result,在这种情况下修改源代码列表不是最佳习惯(可能存在多线程问题)

请将代码更改为:

        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); 
Optional result=list.stream()
.filter(s->s.str.equals(“ccc”)| | s.str.equals(“bbb”))
.findFirst()
.map(s->{
//s.str=“DDD”这很好用
s=新的测试类(“DDD”);
返回s;
} );
系统输出打印项次(结果);
然后再跑一次-它会给你一些提示


请注意,在您的版本中根本不使用result,在这种情况下修改源列表不是最好的习惯(可能存在多线程问题)

您正在方法中分配一个新的对象

您的新引用仅在方法范围内有效,但一旦返回,该引用将指向其原始实例

java
中,这是预期的行为

例如:

在哪里

但是,没有人禁止您更改对象属性,就像您对
s.str=“DDD”
所做的那样(当然,除非您的对象是不可变的)


在您的特定情况下,您没有对
map
lambda结果执行任何操作,因此您的更改将丢失

实际上,在您的情况下,
map
是没有用的,即使您只是执行
s.str=“DDD”
,因为它可以在
forEach
中执行

但是。由于您只处理一个结果,甚至可能不存在(可选),因此应该使用

...findFirst().ifPresent(s -> s.str = "DDD" );

仅当需要将对象转换为不同类型以进行进一步处理时,才应使用
map

您正在方法中指定一个新的对象

您的新引用仅在方法范围内有效,但一旦返回,该引用将指向其原始实例

java
中,这是预期的行为

例如:

在哪里

但是,没有人禁止您更改对象属性,就像您对
s.str=“DDD”
所做的那样(当然,除非您的对象是不可变的)


在您的特定情况下,您没有对
map
lambda结果执行任何操作,因此您的更改将丢失

实际上,在您的情况下,
map
是没有用的,即使您只是执行
s.str=“DDD”
,因为它可以在
forEach
中执行

但是。由于您只处理一个结果,甚至可能不存在(可选),因此应该使用

...findFirst().ifPresent(s -> s.str = "DDD" );

仅当需要将对象转换为不同类型以进行进一步处理时,才应使用
map

使用“map”方法将每个元素映射到其相应的结果。如果要更改列表中的一个元素,则需要将结果收集到新列表中。使用.collect()方法

List List=new ArrayList();
添加(新的测试类(“aaa”);
添加(新的测试类(“bbb”);
利斯
...findFirst().ifPresent(s -> s.str = "DDD" );
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);
    }
List<TestClass> result = list.stream()
            .map( s -> s.toString().equals("bbb") ? new TestClass("DDD") : s)
            .collect(Collectors.toList());