最近休五一假期,不是很想写长篇大论,因此最近三篇文章都是信手拈来的小总结。等假期结束开工之后自然会恢复正常。
java.util.Arrays.asList()方法是我们在日常工作中极其常用的方法之一,它可以方便地将数组类型转化为列表类型。例如:
String[] teamsArray = { "Liverpool", "Man Utd", "Man City", "Arsenal", "Chelsea" };
List<String> teamsList = Arrays.asList(teamsArray);
System.out.println(teamsList.size());
teamsList.forEach(s -> System.out.println(s));
输出一切正常。
但是,如果这样呢?
int[] intArray = { 11, 22, 33, 44, 55 };
List intList = Arrays.asList(intArray);
System.out.println(intList.size());
intList.forEach(i -> System.out.println(i));
输出就会变成只有一个元素:
来看一下asList()方法的实现就明白了。
@SafeVarargs
@SuppressWarnings("varargs")
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
很显然,T必须是对象才能有对应的class,从而支持泛型。当传入int[]这样的基本类型的数组时,就会将数组本身当作一个对象传入,因此返回的List长度为1,且包含有该int数组。要避免这种情况,声明数组时需要用装箱类,即Integer[]。
另外,如果对asList()方法返回的列表进行增删操作,通通都会抛出UnsupportedOperationException异常。例如:
String[] teamsArray = { "Liverpool", "Man Utd", "Man City", "Arsenal", "Chelsea" };
List<String> teamsList = Arrays.asList(teamsArray);
teamsList.add("Tottenham");
teamsList.remove("Man City");
结果:
其原因是,在asList()方法中返回的ArrayList并不是我们常见的java.util.ArrayList,而是在Arrays类中定义的一个静态内部类的实例。
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;
ArrayList(E[] array) { a = Objects.requireNonNull(array); }
@Override
public int size() { return a.length; }
@Override
public Object[] toArray() { return a.clone(); }
@Override
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
int size = size();
if (a.length < size)
return Arrays.copyOf(this.a, size,
(Class<? extends T[]>) a.getClass());
System.arraycopy(this.a, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
@Override
public E get(int index) { return a[index]; }
@Override
public E set(int index, E element) {
E oldValue = a[index];
a[index] = element;
return oldValue;
}
@Override
public int indexOf(Object o) {
E[] a = this.a;
if (o == null) {
for (int i = 0; i < a.length; i++)
if (a[i] == null)
return i;
} else {
for (int i = 0; i < a.length; i++)
if (o.equals(a[i]))
return i;
}
return -1;
}
@Override
public boolean contains(Object o) { return indexOf(o) != -1; }
@Override
public Spliterator<E> spliterator() { return Spliterators.spliterator(a, Spliterator.ORDERED); }
@Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
for (E e : a) {
action.accept(e);
}
}
@Override
public void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
E[] a = this.a;
for (int i = 0; i < a.length; i++) {
a[i] = operator.apply(a[i]);
}
}
@Override
public void sort(Comparator<? super E> c) { Arrays.sort(a, c); }
}
可见,它虽然继承了AbstractList抽象类,但并没有实现add()/remove()/clear()等方法,并且它内部存储元素的数组a用了final关键字修饰,说明它确实不支持使其长度发生改变的修改操作。要想添加或删除元素,就只能用它构造一个真正的java.util.ArrayList再进行操作了。
网友评论