為列表中的元素設置默認值
一、概述
在 Java 中,有時在使用List,
時,我們可能希望為列表中的元素設置一個默認值。例如,這在初始化列表時很有用。
在本教程中,我們將探討在 Java 中為List
中的元素設置默認值的不同方法。
2. 使用Arrays.fill()
首先,假設我們要創建一個包含五個String
元素的列表。此外,我們希望字符串“new”
成為默認值:
List<String> EXPECTED_LIST = Lists.newArrayList("new", "new", "new", "new", "new");
標準 API 提供Arrays.fill()
方法來用相同的值填充整個數組。因此,我們可以先用默認值初始化一個數組,然後使用Arrays.asList().
將數組轉換為List
。
接下來,讓我們實現這個想法。為簡單起見,我們將使用單元測試斷言來驗證我們是否可以從每種方法中獲得預期的列表:
String[] strings = new String[5];
Arrays.fill(strings, "new");
List<String> result = Arrays.asList(strings);
assertEquals(EXPECTED_LIST, result);
上面的實現非常簡單。但是,我們應該注意**Arrays.asList()
創建了一個固定大小的列表。如果我們嘗試向列表中add()/
remove()
元素,它會引發UnsupportedOperationException
** :
assertThrows(UnsupportedOperationException.class, () -> result.add("a new string"));
assertThrows(UnsupportedOperationException.class, () -> result.remove(0));
但是我們可以使用set()
方法更改元素的值,例如:
result.set(2, "a new value");
assertEquals("a new value", result.get(2));
3. 創建newListWithDefault()
方法
如果我們需要用默認值初始化一個可變列表,我們可以創建一個列表對象,然後添加默認值。當然,我們可以創建一個靜態方法來完成這項工作:
static <T> List<T> newListWithDefault(T value, int size) {
List<T> list = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
list.add(value);
}
return list;
}
由於newListWithDefault()
是一個泛型方法,我們可以創建不同類型的列表:
List<String> result = newListWithDefault("new", 5);
assertEquals(EXPECTED_LIST, result);
List<Integer> intList = newListWithDefault(42, 3);
assertEquals(Lists.newArrayList(42, 42, 42), intList);
由於newListWithDefault()
返回常規ArrayList,
我們可以對其應用任何更改,例如add()
、 remove()
和set()
。
4. 如果元素是可變的怎麼辦?
在我們的整個探索過程中,我們研究了兩種使用默認值初始化列表的方法:使用Arrays.fill(),
利用我們自製的newListWithDefault()
方法。
為簡單起見,我們使用不可變類型String
作為列表元素的示例。但我們應該注意,這些方法在與可變值一起使用時表現不同。在涉及可變對象的情況下,列表中的所有元素都將引用同一個對象。因此,修改一個元素的值將影響所有其他元素的值。
下面我們以Collections.nCopies()
方式為例來看問題:
static final Date DATE_EPOCH = Date.from(Instant.EPOCH);
static final Date DATE_NOW = new Date();
List<Date> dateList = Collections.nCopies(2, Date.from(Instant.EPOCH));
assertEquals(Lists.newArrayList(DATE_EPOCH, DATE_EPOCH), dateList);
dateList.get(0).setTime(DATE_NOW.getTime());
assertEquals(Lists.newArrayList(DATE_NOW, DATE_NOW), dateList);
如我們所見,首先,我們將Epoch
作為默認值並創建一個包含兩個Date
的列表。由於列表中的所有元素都引用同一個對象,因此修改一個元素的值會導致所有元素的值發生變化。
如果我們需要列表中的元素是不同的對象,我們可以通過將默認的“ T value
”替換為Supplier<T>
來更改我們的newListWithDefault()
方法:
static <T> List<T> newListWithDefault2(Supplier<T> supplier, int size) {
List<T> list = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
list.add(supplier.get());
}
return list;
}
現在,讓我們使用newListWithDefault2()
方法初始化一些列表,並驗證它是否包含不同的對象:
List<String> result = newListWithDefault2(() -> "new", 5);
assertEquals(EXPECTED_LIST, result);
List<Date> dateList = newListWithDefault2(() -> Date.from(Instant.EPOCH), 2);
assertEquals(Lists.newArrayList(DATE_EPOCH, DATE_EPOCH), dateList);
dateList.get(0).setTime(DATE_NOW.getTime());
assertEquals(Lists.newArrayList(DATE_NOW, DATE_EPOCH), dateList);
從上面的測試中我們可以看出, newListWithDefault2()
將Supplier
函數作為參數並生成具有默認值的列表。此外,當元素是可變類型時,更改一個元素不會影響其他元素。
5.結論
在本文中,我們探索了使用默認值初始化列表的各種方法。此外,我們還學會了使用Supplier
函數來提供默認值,以便列表中的每個元素都引用不同的對象。
與往常一樣,此處提供的所有代碼片段都可以在 GitHub 上找到。