2013-07-04 105 views
0

我有這段代碼。它應該按整數值排序地圖。爲什麼參考自動更新?

public class Main { 

    public static void main(String[] args) { 

     HashMap<String,Integer> map = new HashMap<>(); 
     ValueComparator bvc = new ValueComparator(map); 
     TreeMap<String,Integer> sorted_map = new TreeMap<>(bvc); 

     map.put("A",5); 
     map.put("B",4); 
     map.put("C",4); 
     map.put("D",2); 

     System.out.println("unsorted map: "+map); 

     sorted_map.putAll(map); 

     System.out.println("results: "+sorted_map); 


    } 
} 

class ValueComparator implements Comparator<String> { 

    Map<String, Integer> base; 
    public ValueComparator(Map<String, Integer> base) { 
     this.base = base; 
     System.out.println("Map: " + base); 
    } 

    public int compare(String a, String b) { 
     if (base.get(a) >= base.get(b)) { 
      return -1; 
     } else { 
      return 1; 
     } 
    } 
} 

它工作正常。 但首先作爲ValueComparator實例的參數,我給構造函數一個空的hashmap。而這個空的地圖保存在基地。然後我用比較器創建樹圖。然後我把東西放在地圖上,它會自動更新ValueComparator中名爲的基準。爲什麼地圖會自動傳遞給ValueComparator更新?其實基地變量應該仍然是一個空的地圖。不是嗎?

回答

0

實際上基座變量應該還是一個空映射。不是嗎?

沒有,你叫ValueComparator bvc = new ValueComparator(map);

兩個地圖和底圖都指的是同一個對象,因爲this.base = base;

和上面的那一刻證明爲什麼「然後我把東西在地圖上,它會自動更新ValueComparator中引用base的引用「發生了。

2

Java中的所有變量都通過值(參考值的副本)過去了,所以你將有2個變量指向同一個對象。所以,當你發生變異該對象它反映了另外一個。

例如:

public class Test{ 

public static void main(String args []){ 
    Test test = new Test(); 
    Collection<String> collection = new LinkedList<>(); 
    collection.add("a"); 
    collection.add("b"); 
    someMethod(collection); 
    System.out.println(collection); // will print [a,b]; 
    modifyCollection(collection); 
    System.out.println(collection); // will print [a,b,c]; 
} 

public void modifyCollection(Collection collection){ 
    collection.add("c"); 
} 

public void someMethod(Collection collection){ 
    collection = new ArrayList(); 
    collection.add("nasda"); 
} 

} 
0

在Java中,對類的引用是通過按值。所以,當你通過空HashMapValueComparator,你實際上是在bvc存儲對它的引用。然後,當您修改HashMap,bvc.base作爲對其的引用時,它會自動更新。

編輯:考慮到喬恩斯基特的答覆。

+0

沒有,Java是傳值 - 但* *基準是按值傳遞。通過引用的方式來調用它會讓那些理解真實通過引用的人感到困惑。 –

+0

情況總是如此嗎?所以我可以將字符串傳遞給構造函數,然後更改字符串,然後在構造類中輸出字符串的方法。它會是新的字符串嗎? – MinecraftShamrock

+0

@MinecraftShamrock字符串是不可變的。但是,如果您在方法中重新分配字符串,將其從調用方中返回,並返回sys.out,則您將擁有與調用方法之前相同的值。這就使得java非常清楚地傳遞了這個事實。 –

0

爲什麼地圖會自動傳遞給ValueComparator更新?

當您將object變量傳遞給方法時,您傳遞reference variable的副本。因此,調用方和被調用方法現在都將具有相同的參考副本,因此兩者在堆上都指向相同的確切object。這就是爲什麼通過一個變量對對象所做的更改會被另一個變量看到。
這就是爲什麼傳遞給ValueComparator更新map自動當你把東西放在map