簡體   English   中英

Optional.map-它如何工作?

[英]Optional.map - how does it work exactly?

我試圖研究Java 8中的Optional問題。我編寫了一個非常簡單的程序,該程序由一個類和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);   
    }

隨着s.str = "DDD"修改突變TestClass列表中設置它的實例str領域重視DDD

使用s = new TestClass("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); 

然后再次運行-它應該會給您一些提示。

請注意,您根本不會在版本中使用結果,在這種情況下修改源列表不是最佳習慣(可能存在多線程問題)

您正在分配方法中的一個新的對象。

您的新引用僅在方法范圍內有效,但是一旦返回,該引用將指向其原始實例。

java這是預期的行為。

例如:

String s = "foo";
changeString(s);
print(s); // prints "foo"

哪里

void changeString(String s) {
    s = "bar";
}

但是,沒有s.str = "DDD"您使用s.str = "DDD"那樣禁止您更改對象屬性(當然,除非您的對象是不可變的)。


在您的特定情況下,您對map lambda結果不做任何事情,因此您所做的更改會丟失。

實際上,即使您只是執行s.str = "DDD"map對於您來說還是沒有用的,因為它可以在forEach完成。

但是 由於您只處理一個結果,甚至可能不存在(可選),因此應使用

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

僅當需要將對象轉換為其他類型以進行進一步處理時,才應使用map

'map'方法用於將每個元素映射到其相應的結果。 如果要更改列表的一個元素,則需要將結果收集到新列表中。 使用.collect()方法。

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);
    }

結果是:
aa
DDD
抄送

整理流:

List<TestClass> result = list.stream()
            .map( s -> s.toString().equals("bbb") ? new TestClass("DDD") : s)
            .collect(Collectors.toList());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM