集合①只能存放对象,存放基本类型会自动转成对应的对象②能够存放不一样类型的对象(若是不使用泛型的话),且不限数量③集合中存放的只是对象的引用
集合详解
html
Collection继承了该接口,因此Collection的实现类均可以使用Iterator()
方法来得到迭代器,从而遍历集合java
public interface Iterable<E> { Iterator<E> iterator();//return a Iterator Object }
迭代器可使用for-each代替。迭代器至关于一个在两个元素之间的指针(首尾元素除外),使用remove()
删除元素以前,须要先调用next()
越过该元素。若是调用next()
以后,集合发生了改变,再接着调用remove()
则会抛出异常。算法
public interface Iterator<E>{ E next();//返回迭代器刚越过的元素的引用 boolean hasNext();//判断容器内是否还有可供访问的元素 void remove();//删除迭代器刚越过的元素,因此要删除则必须先越过 }
ListIterator接口继承了Iterator接口,并添加了一些方法,使得能够向前和向后遍历。数组
add set//修改越过的元素 previous hasPrevious nextIndex//返回下一次调用next方法返回的元素的索引 previousIndex
获取迭代器默认其指针是在第一个元素的前面,能够经过给定一个参数n来指定指针位置为第n个元素的前面(ListIterator有,Iterator没有这个),不过获取这样的迭代器消耗的时间比默认状态的迭代器要高一些。另外须要注意的是remove依赖迭代器的状态,add只依赖迭代器的位置安全
Collection接口定义了不少方法,开发者若是要开发本身的集合类,能够继承AbstractCollection抽象类,该类实现了Collection的不少方法,可是还有size()
和Iterator()
没实现数据结构
方法 | 描述 |
---|---|
iterator() |
获取迭代器 |
size() |
元素个数 |
isEmpty() |
判断有无元素 |
clear() |
清空集合 |
contains() |
是否包含给定元素 |
containsAll() |
是否包含给定集合全部元素 |
add() |
添加元素 |
addAll() |
添加给定集合全部元素 |
remove() |
删除元素 |
removeAll() |
删除给定集合中全部元素 |
retainAll() |
删除给定集合中不存在的元素,即取交集 |
toArray() |
返回集合的对象数组 |
toArray(array) |
同上,不过指定一个数组参数 |
List能够得到ListIterator迭代器,List能够有重复的元素,元素能够按照使用者的意愿排序,元素的位置跟元素的值没有关系,所以称为有序ide
addFirst addLast getFirst getLast removeFirst removeLast
Set不能够有重复的元素,只能用Iterator迭代器,不能使用ListIterator迭代器性能
LinkedHashSet
不能够重复,判断重复的标准是equals为true,且hashCode相等,有序(记录了插入顺序)。由于底层采用链表和哈希表的算法。链表保证元素的添加顺序,哈希表保证元素的惟一性this
队列能够有效的在队列尾部添加元素,头部删除元素。双端队列能够同时在尾部和头部添加和删除元素,不过不能够在中间。ArrayDeque和LinkedList实现了双端队列spa
底层数据结构是堆(heap)。典型示例为任务调度。优先级队列跟TreeSet同样,须要元素实现Comparable接口或在构造时提供Comparator比较器。不管以什么顺序插入,remove()的老是优先级队列里最小的元素,然而优先级队列并无对全部元素进行排序,只是确保了remove出来的是最小的元素
映射表存储的是键值对,Map不能使用for-each循环进行遍历,由于它既不是Collection系列,也没继承Iterable接口
//Map的方法 put get putAll containsKey containsValue Set<Map.Entry<K,V>> entrySet()//后面3个方法返回的是Map的视图,能够经过这三个集修改和删除元素,则Map中也会相应改变,可是不能添加元素 Set<K> keySet() Collection<V> values() //Entry的方法 getKey getValue setValue
HashMap
对键进行散列,键不容许重复,容许为null(最多一个),判断键重复的标准是键的equals为true,且键的hashCode相等
TreeMap
对键进行排序,用键的顺序对元素进行排序,键不容许重复,判断键重复的标准是键compareTo或compare为0
LinkedHashMap
与HashMap相似,只是多了链表保证键有序(记录了访问顺序,每次因调用了get/set方法受到影响的元素都会从当前链表位置删除,放到链表末尾,但注意在桶中的位置是不会受影响的)
WeakHashMap
弱散列映射表
Hashtable
与HashMap同样,不过线程安全,性能低
Properties
Hashtable的子类,要求键值都是字符串,通常用于配置文件
都有几个类型的集合。HashMap 和 HashSet ,都采哈希表算法;TreeMap 和 TreeSet 都采用 红-黑树算法;LinkedHashMap 和 LinkedHashSet 都采用 哈希表算法和红-黑树算法。分析 Set 的底层源码,咱们能够看到,Set 集合 就是 由 Map 集合的 Key 组成,只不过Value是同一个Object对象
Arrays.asList()
String[] strs = new String[10]; List<String> list = Arrays.asList(strs);//list是原数组的视图
集合转数组
toArray(数组)
HashSet<String> staff = new HashSet<>(...); String[] strs = staff.toArray();//error String[] strs = staff.toArray(new String[0]);//ok String[] strs = staff.toArray(new String[staff.size()]);//ok
int[] a1 = {1, 3}; int[] a2 = a1.clone(); a1[0] = 666; System.out.println(Arrays.toString(a1)); //[666, 3] System.out.println(Arrays.toString(a2)); //[1, 3] String[] s1 = {"a1", "a2"}; String[] s2 = s1.clone(); a1[0] = "b1"; //更改a1数组中元素的值 System.out.println(Arrays.toString(s1)); //[b1, a2] System.out.println(Arrays.toString(s2)); //[a1, a2]
System.arraycopy
System.arraycopy是一个本地方法,源码定义以下
public static native void arraycopy(Object src, int srcPos, Object dest, int desPos, int length) //参数含义(原数组, 原数组的开始位置, 目标数组, 目标数组的开始位置, 拷贝长度)
Arrays.copyOf
Arrays.copyOf底层其实也是用的System.arraycopy ,参数含义(原数组,拷贝长度)源码以下:
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) { @SuppressWarnings("unchecked") T[] copy = ((Object)newType == (Object)Object[].class) ? (T[]) new Object[newLength] : (T[]) Array.newInstance(newType.getComponentType(), newLength); System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; }
Arrays.copyOfRange
Arrays.copyOfRange底层其实也是用的System.arraycopy,只不过封装了一个方法,参数含义(原数组,开始位置,拷贝长度)
public static <T,U> T[] copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) { int newLength = to - from; if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); @SuppressWarnings("unchecked") T[] copy = ((Object)newType == (Object)Object[].class) ? (T[]) new Object[newLength] : (T[]) Array.newInstance(newType.getComponentType(), newLength); System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength)); return copy; }
@Override public Cat clone() throws CloneNotSupportedException { Cat cat = (Cat) super.clone(); return dog; }
public Cat myClone() { Cat cat = null; try { //将对象序列化成为流,由于如今流是对象的一个拷贝 //而原始对象仍然存在于JVM中,因此利用这个特性能够实现深拷贝 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(this); //将流序列化为对象 ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream); cat = (Cat) objectInputStream.readObject(); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } return cat; }