public static void main(String[] args) {
Integer[] datas = {1,2,3,4,5};
List<Integer> list = Arrays.asList(datas);
list.add(5);
System.out.println(list.size());
}
此题结果为:运行异常,不允许添加元素
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at T.main(T.java:23)
换个赋值方式
public static void main(String[] args) {
Integer[] datas = {1,2,3,4,5};
List<Integer> list = new ArrayList<>(Arrays.asList(datas));
list.add(5);
System.out.println(list.size());
}
结果为
6
如我第一次理解的过程,声明并赋值创建一个Integer类型的数组,然后用asLIst()的返回值赋值list,实例变量使用add()方法,并输出size大小。但我理解错误了asList方法的实现原理。给出asList源码:
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
/**
* @serial include
*/
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);
}
}
根据以上可以知道asList方法返回的ArrayList数组并非List接口下的ArrayList实现,而是一个新的重写子类,子类中并没有add()方法。
最后我介绍一下常用集合
集合常用两大类Collection和Map
这两大接口都实现了Comparable和Comparator接口,以及继承Collections工具类(该类内都是静态方法)
- Collection(单列数据集合)
作为父类接口,Collection本身含有十一类基本方法
包括两个子类常用接口List和Set
- List
基本特征:为有序重复(有序指存储顺序为遍历顺序)
扩容方式:*1.5(Vector:*2)
基本方法:
add();将目标元素整体加入
addAll();与上方法不同之处是他将数组等组合元素拆分分别加入
get();
set();
indexOf();
lastIndexOf();
remove();
subList();取目标位置的元素生成子数组
实现类:
ArrayList(动态数组):JDK1.7使用饿汉式单例设计,JDk1.8使用懒汉式单例设计
LinkedList(双向链表)
Vector(数组,线程安全)
- Set
基本特征:为无序无重复(有序指存储顺序为遍历顺序),判断是否一致的方法(hashcode一致且equals为true)
扩容方式:当元素数量超过负载因子后(0.75*cap)*2
基本方法:
实现类:
HashSet:底层由数组实现,hashmap:根据存入数据的hashcode以一个散列函数为根据决定其存储位置
这意味着修改一个已知元素会改变其hashcode但不改变其存储位置,remove时先根据hashcode寻找元素,但目标位置不是原修改元素位置,故会remove:false。
LinkedSet:由hashset实现,是其子类,但使用双向链表实现有序,迭代性能优于hashset插入性能低于hashset。
TreeSet:实现了SortedSet接口,基于treemap,用红黑树结构存储元素,添加自定义类元素需要实现接口和重写equals()
- 自然排序:comparable 的compareTo();
- 定制排序:comparator 的comoare();
- Map(双列数据集合:key-value映射关系)
作为父类接口,Map本身基本方法
实现类:
HashMap:底层使用哈希表,JDK1.7用数组和链表结构构成,JDK1.8用数组链表红黑树构成(添加元素时,当某一链长为8,首先判断总的容量是否大于64,是则将此链转化为红黑树,否则以扩容方式修改整个map)。
Hashtable:继承自Dictionary,与HashMap相比线程安全,添加元素方面不允许添加NULL。
TreeMap:
LinkedHashMap:
Properties:处理属性文件,属性为String。