將列表複製到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
版本和此過程中產生的常見錯誤。