簡體   English   中英

如何獲取和更改哈希圖的值,而不更改 Java 中的哈希圖本身?

[英]How to get and change a value of a hashmap, without changing the hashmap itself in Java?

我有一個 HashMap 如下,

Map<String, MyClass> testMap = new HashMap<>();
map.put("1", myClass1);
map.put("2", myClass2);

這里MyClass是一個 bean 類。 現在我希望獲得testMap的值,並在不更改testMap本身的情況下更改該值。 我所做的如下,

MyClass result = testMap.get("1");
if (some conditions){
    do someting to result;
}
return result;

我期望的是result發生變化而testMap保持不變。 但實際上myClass1中的testMap發生了變化。 那么我怎樣才能實現我的目標呢?

有多種方法可以實現:

  1. 當你從testMap取出一個對象時,你首先手動將它復制到一個相同類型的新對象中。 在 C++ 中,這通常使用復制構造函數來實現: new MyClass1(myClass); 復制構造函數獲取傳入的對象的所有字段並將其復制到一個新對象中,在 Java 中這有時是使用Cloneable接口完成的。
  2. 使您的對象不可變,以便對象的更改永遠不會更改其狀態,但始終返回包含這些更改的新對象。 一個相對較新的例子是BigDecimal ,其中對BigDecimal對象的每個操作總是返回一個新的BigDecimal對象。

它可以通過創建不可變對象來實現。 當您更改此對象的值時,它將始終創建一個新對象並且不會更改原始值。

MyClass 的不可變實現:

public class MyClass {
    private final String name;

    public MyClass(String name) {
        this.name = name;
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

}

客戶端驗證不變性:

import java.util.HashMap;
import java.util.Map;

public class Test {
    public static void main(String[] args) {
        MyClass myClass = new MyClass("class1");
        System.out.println("Object " + myClass);

        Map<Integer, MyClass> map = new HashMap<Integer, MyClass>();
        map.put(1, myClass);

        MyClass result = map.get(1);
        System.out.println("From Map Object " + result);
        String name = result.getName();
        if (name != null && name.equals("class1")) {
            MyClass updatedResult = new MyClass("updatedclass1 ");
            System.out.println("Updated Object " + updatedResult);
        }
        System.out.println("From Map Object " + result);

    }
}

輸出:

Object MyClass@6d06d69c
From Map Object MyClass@6d06d69c
Updated Object MyClass@7852e922
From Map Object MyClass@6d06d69c

更新地圖后保持不變。

您需要制作 MyClass 的副本。 如果您對其中的對象有引用,則需要深拷貝。

在地圖中,它存儲對對象的引用。 因此,當您從地圖中獲取對該對象的引用並對其進行修改時,您正在修改該對象的同一個實例。 如果您制作了一份副本,您將能夠對其中一個進行更改,但不能對另一個進行更改。

淺拷貝與深拷貝

淺拷貝可以用.clone()完成,但是只拷貝所有的字段,如果類中有對象作為字段,則只拷貝引用。 這是有問題的,因為您將在每個副本中擁有相同的內部對象副本,並且最終會遇到與上述相同的情況 - 當您修改任何這些對象時,您也會修改其他對象。

深度復制緩解了這個問題,因為它也復制了內部對象。 您可以遍歷並遞歸復制、通過序列化復制或外部庫(如 Apache Commons Lang SerializationUtils.clone())。 如果您好奇,此鏈接有更多詳細信息。 https://www.baeldung.com/java-deep-copy

暫無
暫無

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

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