將列表複製到Java中的另一個列表

1.概述

在本快速教程中,我們將展示將List複製到另一個List不同方法,以及在此過程中產生的常見錯誤。

有關使用Collections ,請在此處參考本文。

2.構造函數

複製List一種簡單方法是使用將集合作為其參數的構造函數:

List<Plant> copy = new ArrayList<>(list);

由於我們要在此處複製引用而不是克隆對象,因此,對一個元素進行的每次修改都會影響兩個列表。

因此,使用構造函數可以復制不可變的對象:

List<Integer> copy = new ArrayList<>(list);

Integer是一個不可變的類,其值在創建實例時設置,並且永不更改。

這樣,一個Integer引用可以被多個列表和線程共享,並且任何人都無法更改其值。

3. List ConcurrentAccessException

使用列表的一個常見問題是ConcurrentAccessException這可能意味著我們在嘗試複製列表時正在修改列表,很可能是在另一個線程中進行。

要解決此問題,我們必須:

  • 使用專為並發訪問而設計的集合
  • 適當地鎖定集合以對其進行迭代
  • 找到一種避免複製原始集合的方法

考慮到我們的最後一種方法,它不是線程安全的。因此,如果要使用第一個選項解決問題,則可能需要使用CopyOnWriteArrayList ,其中所有變異操作都通過對基礎數組進行全新復制來實現。

有關更多信息,請參考本文。

如果我們想鎖定Collection ,可以使用鎖定原語來序列化讀/寫訪問,例如ReentrantReadWriteLock

4. AddAll

複製元素的另一種方法是使用addAll方法:

List<Integer> copy = new ArrayList<>();

 copy.addAll(list);

使用此方法時,請務必記住,與構造函數一樣,兩個列表的內容都將引用相同的對象。

5. Collections.copy

Collections類僅由對集合進行操作或返回集合的靜態方法組成。

其中之一是copy ,它需要一個源列表和一個目標列表,其長度至少與源一樣長。

它將維護目標列表中每個複制元素的索引,例如原始索引:

List<Integer> source = Arrays.asList(1,2,3);

 List<Integer> dest = Arrays.asList(4,5,6);

 Collections.copy(dest, source);

在上面的示例中, dest列表中的所有先前元素都被覆蓋,因為兩個列表的大小相同。

如果目標列表的大小大於源列表的大小:

List<Integer> source = Arrays.asList(1, 2, 3);

 List<Integer> dest = Arrays.asList(5, 6, 7, 8, 9, 10);

 Collections.copy(dest, source);

僅保留了前三個項,而保留了列表中的其餘元素。

6.使用Java 8

此版本的Java通過添加新工具為我們打開了可能性。我們將在下一個示例中探索的是Stream

List<String> copy = list.stream()

 .collect(Collectors.toList());

這種方式的主要優點是可以使用跳過和過濾器。在下一個示例中,我們將跳過第一個元素:

List<String> copy = list.stream()

 .skip(1)

 .collect(Collectors.toList());

也可以通過String的長度或通過比較對象的屬性來進行過濾:

List<String> copy = list.stream()

 .filter(s -> s.length() > 10)

 .collect(Collectors.toList());
List<Flower> flowers = list.stream()

 .filter(f -> f.getPetals() > 6)

 .collect(Collectors.toList());

我們可能想以null安全的方式工作:

List<Flower> flowers = Optional.ofNullable(list)

 .map(List::stream)

  .orElseGet(Stream::empty)

  .collect(Collectors.toList());

並也使用這種方式跳過元素:

List<Flower> flowers = Optional.ofNullable(list)

  .map(List::stream).orElseGet(Stream::empty)

  .skip(1)

  .collect(Collectors.toList());

7.使用Java 10

最後,最後一個Java版本之一允許我們創建一個包含給定Collection:元素的不可變List Collection:

List<T> copy = List.copyOf(list);

唯一的條件是給定的Collection不能為null,並且不得包含任何null元素。

8.結論

在本文中,我們探索了多種方法來複製 List另一個 List不同 Java版本和此過程中產生的常見錯誤。

與往常一樣,可以在GitHub上找到代碼示例 在這里在這裡