2017-02-06 57 views
0

我基本上只是試圖做一個零和一個深的副本,所以我可以使用布爾值,但我想知道如何在整數的genereal做到這一點。如何在Java中製作ArrayList <Integer>的深層副本?

private ArrayList<Integer> makeDeepCopyInteger(ArrayList<Integer> a) { 
    ArrayList<Integer> newA = new ArrayList<>(a.size()); 
    for (int i = 0; i < a.size(); i++) { 
     int newInt = 0; 
     if (a.get(i) == 1) { 
      newInt = 1; 
     } 
     newA.add(newInt); 
    } 
    return newA; 
} 
+10

由於整數是不可變的,你爲什麼要深拷貝它們? –

回答

1

clone()方法是通過保護Integer班,所以您不能在該班級之外撥打Integer.clone()。你可以做的是創建一個new Integer。

private ArrayList<Integer> makeDeepCopyInteger(ArrayList<Integer> old){ 
    ArrayList<Integer> copy = new ArrayList<Integer>(old.size()); 
    for(Integer i : old){ 
     copy.add(new Integer(i)); 
    } 
    return copy; 
} 

您可以測試這個工程做一樣的東西:

public static void main (String[] args) throws java.lang.Exception 
{ 
    ArrayList<Integer> arr = new ArrayList<>(); 
    for(int i = 0; i<5; i++){ 
     arr.add(new Integer(i)); 
    } 
    ArrayList<Integer> x = makeDeepCopyInteger(arr); 
    for(int i = 0; i<x.size(); i++){ 
     if(arr.get(i) == x.get(i)){ 
      System.out.println("Same object"); 
     } else { 
      System.out.println("Not the same object"); 
     } 
    } 
} 

測試

Integer a = new Integer(1); 
Integer b = new Integer(a); 

System.out.println(a==b); // true 
System.out.println(System.identityHashCode(a) == (System.identityHashCode(b))); // false; 


Integer a = new Integer(1); 
Integer b = a; 

System.out.println(a==b); // true 
System.out.println(System.identityHashCode(a) == (System.identityHashCode(b))); // true 
從我的測試看來,創建用於複製一個新的參考

所以到一個新的陣列,你應該使用new Integer()Integer是不可變的對象,但當Integer的值更改時引用會更改。

+2

因爲'Integer'是不可變的,所以你不需要*創建它的副本。 – Kayaman

+0

@Kayaman我對此做了一些測試,請參閱我的編輯。也許我很困惑,但不創建一個副本,似乎保留了舊的參考。 – px06

+0

這沒什麼錯。由於'Integer'的值不能改變,所以如果你有1000個列表全都引用同一個'17',那就沒有關係。你的最後一段是錯誤的。由於'Integer'是不可變的,它的值不能改變。 – Kayaman

1

使用流複製對象。易於閱讀,適合JIT。以下代碼提供了一個帶有Integer對象副本的列表副本。

private ArrayList<Integer> makeDeepCopyInteger(ArrayList<Integer> a){ 
    return a.stream().map(val -> new Integer(val)).collect(toList()); 
} 

要複製自定義對象不是整數來覆蓋其他實施並調用clone()

return a.stream().map(MyObjectClass::clone).collect(toList()); 

相反,克隆可以使用序列化到JSON的。例如。在以下java-utils

+1

歡迎使用堆棧溢出:-) 請看[answer]。您應該提供一些信息,說明爲什麼您的代碼可以解決問題。 僅有代碼的答案對社區沒有用處。 – JimHawkins

0

您在BeanUtils.getCopy(sourceBean)使用可以做這樣的事情:

public static List<Integer> clone(List<Integer> source) { 
    return source.stream() 
     .map(intObj -> new Integer(intObj.intValue())) 
     .collect(Collectors.toList()); 
} 

或者,更老套:

public static List<Integer> clone(List<Integer> source) { 
    List<Integer> newList = new ArrayList<>(); 
    for(Integer intObj : source) { 
     newList.add(new Integer(intObj.intValue())); 
    } 
    return newList; 
} 

這兩種可能通過利用自動裝箱/自動拆箱而縮短。但是我已經明確地說清楚發生了什麼事情。

然而,這是一個毫無意義的練習 - 事實上它積極地浪費了內存並且不利於性能。 Integer是不可變的,所以它的更好參考指向Integer的相同實例。由於Integer無法改變價值,因此不可能通過共享實例造成任何傷害。

這對一般的不可變對象是適用的,這也是它們是件好事的原因。

作爲初學者,作爲new Integer(...)是個好主意(甚至是Integer.valueOf(int i),儘管這可能會返回一個緩存實例),您是不可能的。如果你已經有了一個Integer,使用一個你:

Integer oldVar = ... ; 
Integer newVar = oldVar; 

不變性意味着將永遠是OK。 newVar上的操作無法破壞oldVar,因爲沒有newVar.setValue(newValue)

如果你有一個int直接使用它,並允許Java的自動裝箱把它轉換成一個Integer

int oldValue = ... ; 
Integer newValue = oldValue ; // Java will automatically put this through 
           // Integer.valueOf(int i) 

你提到你真的想與布爾合作。您應該考慮使用BitSet