集合①只能存放对象,存放基本类型会自动转成对应的对象②可以存放不同类型的对象(如果不使用泛型的话),且不限数量③集合中存放的只是对象的引用
集合详解
Collection继承了该接口,所以Collection的实现类都可以使用Iterator()
方法来获得迭代器,从而遍历集合
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可以有重复的元素,元素可以按照使用者的意愿排序,元素的位置跟元素的值没有关系,因此称为有序
addFirst addLast getFirst getLast removeFirst removeLast
Set不可以有重复的元素,只能用Iterator迭代器,不能使用ListIterator迭代器
LinkedHashSet
不可以重复,判断重复的标准是equals为true,且hashCode相等,有序(记录了插入顺序)。因为底层采用链表和哈希表的算法。链表保证元素的添加顺序,哈希表保证元素的唯一性
队列可以有效的在队列尾部添加元素,头部删除元素。双端队列可以同时在尾部和头部添加和删除元素,不过不可以在中间。ArrayDeque和LinkedList实现了双端队列
底层数据结构是堆(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; }
原文:https://www.cnblogs.com/sandea/p/11757229.html