明翰Java教学系列之集合框架篇V0.2(持续更新)
文章目录
- 传送门
- 前言
- 什么是集合框架
- 集合框架体系
- Collection接口
- `Set接口`
- `HashSet`
- LinkedHashSet
- TreeSet
- EnumSet
- Queue接口
- PriorityQueue
- Deque接口
- `List接口`
- `ArrayList`
- LinkedList
- Vector
- `Map接口`
- `HashMap`
- `LinkedHashMap`
- Hashtable
- TreeMap
- WeakHashMap
- IdentityHashMap
- EnumMap
- Collections
- 总结
传送门
杨明翰的Java教学系列之认识Java篇
杨明翰的Java教学系列之基础语法篇
杨明翰的Java教学系列之初级面向对象篇
杨明翰的Java教学系列之数组篇
杨明翰的Java教学系列之进阶面向对象篇
杨明翰的Java教学系列之异常篇
杨明翰的Java教学系列之集合框架篇
前言
存储若干对象到集合中,类似于数组的升级版,
可以对集合中的对象进行存取、遍历等等操作。
集合是非常有用的知识点,
在后面会用到从数据库中查询出来的数据,
返回给我们来使用,
那些数据库中的数据就可以存储在集合之中。
什么是集合框架
Java集合框架提供了一套性能优良,使用方便的接口和类,
Java集合框架位于java.util包中,
所以当使用集合框架的时候需要进行导包。
集合框架是一个用来代表和操纵集合的统一架构,
除了集合,该框架也定义了几个Map接口和类。
Map里存储的是[键/值]对,尽管Map不是Collection,
但是它们完全整合在集合中,
集合框架的类和接口均在java.util包中。
所有的集合框架都包含如下内容:
接口,代表集合的抽象数据类型,只是定义没有实现,接口允许实现类来为其实现细节;
实现(类),是集合接口的具体实现,从本质上讲,它们是可重复使用的数据结构;
算法,是实现集合接口的对象里的方法执行的一些有用的计算。例如:搜索和排序,相同的方法可以在相同的接口上有着不同的实现;
整个集合框架就围绕一组标准接口而设计。
你可以直接使用这些接口的标准实现,
诸如: LinkedList、HashSet、TreeSet等,
除此之外你也可以通过这些接口实现自己的集合。
集合框架体系
集合体系又分为两大分支,
分别为Map接口分支与Collection接口分支。
Map接口与Collection接口是两个接口,千万不要弄混,
Map接口的应用非常广泛,主要用于存储KV结构数据,
这两张图需要牢记并且能拥有徒手画图的能力。
虚线:实现接口
实线:继承父类
箭头方向:子类指向父类&实现类指向接口
Collection接口
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WxG5gY4m-1603362650508)(evernotecid://85A94EB2-9BD2-45DE-A16D-D9C9CD7ECF0B/appyinxiangcom/12192613/ENResource/p298)]
Collection是最基本的集合接口,
Java不提供直接继承自Collection的类,
只提供继承于的子接口(如List和Set等)。
Collection接口是List、Set、Queue接口的父接口,
该接口里定义的方法可以被子接口所使用。
方法 | 描述 |
---|---|
boolean add(Object o) | 该方法用于向集合里添加一个元素。如果集合对象被添加操作改变了,则返回true。 |
boolean addAll(Collection c) | 该方法把集合c里的所有元素添加到指定集合里,如果集合对象被添加操作改变了,则返回true。 |
void clear() | 清除集合里的所有元素,将集合长度变为0。 |
boolean contains(Object o) | 返回集合里是否包含指定元素。 |
boolean containsAll(Collection c) | 返回集合里是否包含集合c里的所有元素。 |
Set接口
Set是Collection的子接口,Set保存无序的、不可重复的元素。
Set检索效率低下,删除和插入效率高,
插入和删除不会引起元素位置改变。
LinkedHashSet的元素有序(插入顺序),
TreeSet的元素有序(比较顺序)。
HashSet的性能总是比TreeSet好,
只有当需要保持排序的Set时,
才应该使用TreeSet,否则都应该使用HashSet。
EnumSet是性能最好的,但是只能保存枚举类型,
HashSet,TreeSet,EnumSet都是线程不安全的。
HashSet
HashSet类实现了Set接口,不允许出现重复元素,
不保证集合中元素的顺序,允许包含值为null的元素,
但最多只能一个。
HashSet不是同步的,线程不安全,
如果多个线程同时访问一个HashSet,
并同时修改了HashSet集合时,
必须通过代码来保证其同步。
如果HashSet中两个以上的元素具有相同的hashCode值,
将会导致性能下降。
hash算法的功能:
它能保证通过一个对象快速查找到另一个对象,
hash算法的价值在于速度,它可以保证查询被快速执行。
当需要查询集合中的某个元素时,
hash算法可以直接根据该元素的值计算出该元素的存储位置,从而让程序快速定位该元素的存储位置。
Set没有顺序且不允许相同的对象添加进集合,
判断标准是使用euqals而不是==,
还有hashCode双重判断,需要注意!
HashSet按Hash算法来存储集合中的元素,
具有很好的存储和查找性能。
LinkedHashSet
LinkedHashSet是HashSet的子类,
它使用链表维护元素的次序,
这使得元素看起来是以插入的顺序保存的。
因为LinkHashSet需要维护顺序,
因此性能上略低于HashSet,
但在迭代访问Set里的全部元素时将有很好的性能。
TreeSet
SortedSet接口继承于Set保存有序的集合,
TreeSet是SortedSet接口的实现类,可以实现排序等功能。
TreeSet采用红黑树的数据结构来存储集合元素,
TreeSet支持两种排序方法:自然排序和定制排序。
在默认情况下,TreeSet采用自然排序。
TreeSet会调用集合元素的compareTo(Object obj)方法,
来比较元素之间的大小关系,然后将集合元素按升序排列,
这种方式就是自然排序。
Java提供了一个Comparable接口,
该接口里定义了一个compareTo(Object obj),
该方法返回一个整数值,
实现该接口的类必须实现该方法,
实现了该接口的类的对象就可以比较大小。
如果试图把一个对象添加到TreeSet时,
则该对象的类必须实现Comparable接口,
否则程序将会抛出一个异常。
如果两个对象通过compareTo(Object obj)比较相等,
新对象将无法添加到TreeSet集合中。
如果通过compareTo(Object obj)比较返回0,
则表示他们相等。
注意,equals相等也不相等了,必须要compareTo等于0才是相等。
在重写equals方法时候,
应该注意保证与compareTo方法由相同的结果。
TreeSet可以确保集合元素处于排序状态(按大小排序),
与HashSet相比,TreeSet还提供了几个额外的方法:
方法 | 描述 |
---|---|
Comparator comparator() | 如果TreeSet采用了定制排序,则该方法返回定制排序所使用的Comparator,如果TreeSet采用了自然排序,则返回null。 |
Object first() | 返回集合中第一个元素。 |
Object last() | 返回集合中最后一个元素。 |
Object lawer(Object e) | 返回集合中位于指定元素之前的元素(即小于指定元素的最大元素,参考元素不需要是TreeSet集合里的元素) |
Object higher(Object e) | 返回集合中位于指定元素之后的元素(即大于指定元素的最小元素,参考元素不需要是TreeSet集合里的元素) |
SortedSet subSet(fromElement,toElement) | 返回此Set的子集合,范围从formElement(包含)到toElement(不包含)。 |
SortedSet headSet(toElement) | 返回此Set的子集,由小于toElement的元素组成。 |
SortedSet tailSet(fromElement) | 返回此Set的子集,由大于或等于fromElement的元素组成。 |
EnumSet
EnumSet是一个专门为枚举类设计的集合类,
EnumSet中的所有元素都必须是指定枚举类型的枚举值,
该枚举类型在创建EnumSet时显式或隐式的指定。
EnumSet的集合元素也是有序的,
EnumSet以枚举值在Enum类内的定义顺序来决定集合元素的顺序。
EnumSet在内部以向量的形式存储,
这种存储形式非常紧凑,高效,
因此EnumSet对象占用内存很小,而且运行效率很好。
EnumSet不允许加入null元素。
方法 | 描述 |
---|---|
static EnumSet allOf(Class elementType) | 创建一个包含指定枚举类里所有枚举值的EnumSet集合。 |
static EnumSet complementOf(EnumSet s) | 创建一个其元素类型与指定EnumSet里元素类型相同的EnumSet集合,新EnumSet集合包含原EnumSet集合所不包含的、此枚举类剩下的枚举值(即新EnumSet集合和原EnumSet集合的集合元素加起来就是该枚举类的所有枚举值。) |
static EnumSet copyOf(Collection c) | 使用一个普通集合来创建EnumSet集合。 |
static EnumSet copyOf(EnumSet s) | 创建一个与指定EnumSet具有相同元素类型、相同集合元素的EnumSet集合。 |
static EnumSet noneOf(Class elementType) | 创建一个元素类型为指定枚举类型的空EnumSet。 |
static EnumSet of(E first,E… rest) | 创建一个包含一个或多个枚举值的EnumSet集合,传入的多个枚举值必须属于同一个枚举类。 |
static EnumSet range(E from,E to) | 创建一个包含从from枚举值到to枚举值范围内所有枚举值的EnumSet集合。 |
Queue接口
Queue用于模拟队列这种数据结构,
队列通常是指“先进先出”(FIFO)的容器。
方法 | 描述 |
---|---|
void add(Object e) | 将指定元素加入此队列的尾部。 |
Object element() | 获取队列头部的元素,但是不删除该元素。 |
boolean offer(Object e) | 将指定元素加入此队列的尾部。当使用有容量限制的队列时,此方法通常比add(Object e)方法更好。 |
Object peek() | 获取队列头部的元素,但是不删除该元素。如果此队列为空,则返回null。 |
Object poll() | 获取队列头部的元素,并删除该元素。如果此队列为空,则返回null。 |
Object remove() | 获取队列头部的元素,并删除该元素。 |
PriorityQueue
PriorityQueue保存队列元素的顺序,
是按队列元素的大小进行重新排序。
因此当调用peek()或者poll(),
取出队列中的元素时,并不是取出最先进入队列的元素,
而是取出队列中最小的元素。(违反了队列先进先出的原则)
PriorityQueue不允许插入null值,
PriorityQueue的元素有两种排序方法:
自然排序:集合中的元素必须实现了Comparable接口,
而且应该是同一个类的多个实例。
定制排序:创建队列时,传入一个Comparator对象,该对象负责对队列中的所有元素进行排序。
Deque接口
Deque接口是Queue接口的子接口,
Deque代表一个“双端队列”,
双端队列可以同时从两端来添加,删除元素,
因此Deque既可以当成队列使用,也可以当成栈使用。
Java为Deque接口提供了,
ArrayDeque和LinkedList两个实现类。
ArrayDeque是Deque接口的实现类,
它是一个基于数组实现的双端队列。
方法 | 描述 |
---|---|
void addFirst(Object e) | 将指定元素插入该双端队列的开头。 |
void addLast(Object e) | 将指定元素插入该双端队列的末尾。 |
Iterator descendingIterator() | 返回该双端队列对应的迭代器,该迭代器将以逆向顺序来迭代队列中的元素。 |
Object getFirst() | 获取但不删除双端队列的第一个元素。 |
Object getLast() | 获取但不删除双端队列的最后一个元素。 |
boolean offerFirst(Object e) | 将指定元素插入该双端队列的开头。 |
boolean offerLast(Object e) | 将指定元素插入该双端队列的末尾。 |
Object peekFirst(Object e) | 获取但不删除该双端队列的第一个元素;如果此双端队列为空,则返回null。 |
Object peekLast(Object e) | 获取但不删除该双端队列的最后一个元素;如果此双端队列为空,则返回null。 |
Object pollFirst(Object e) | 获取并删除该双端队列的第一个元素;如果此双端队列为空,则返回null。 |
Object pollLast(Object e) | 获取并删除该双端队列的最后一个元素;如果此双端队列为空,则返回null。 |
Object pop()(栈方法) | pop出该双端队列所表示的栈的栈顶元素。相当于removeFirst()。 |
void push(Object e) | 栈方法,将第一个元素push进该双端队列所表示的栈的栈顶。相当于addFirst(e)。 |
Object removeFirst() | 获取并删除该双端队列的第一个元素。 |
Object removeFirstOccurrence(Object o) | 删除该双端队列的第一次出现的元素o。 |
void removeLast() | 获取并删除该双端队列的最后一个元素。 |
void removeLastOccurrence(Object o) | 删除该双端队列的最后一次出现的元素o。 |
List接口
~Vector与Stack线程安全,但性能差。
~ArrayList、LinkedList线程不安全。
~LinkedList是双向链表,可做队列&栈。
List是Collection的子接口,
List保存有序的、可重复的元素。
List和数组类似,可以动态增长,
List中的每个元素都有其对应的顺序索引,
根据实际存储的数据的长度自动增长List的长度。
查找元素效率高,插入删除效率低,
因为会引起其他元素位置改变。
使用List能够精确的控制每个元素插入的位置,
能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素。
实现类有:ArrayList、LinkedList、Vector。
List作为Collection的子接口,
可以使用Collection的全部方法,还有一些新增的方法:
方法 | 描述 |
---|---|
void add(int index,Object element) | 将元素element插入到List集合的index处。 |
boolean addAll(int index,Collection c) | 将集合c所包含的所有元素都插入到List集合的index处。 |
Object get(int index) | 返回集合index索引处的元素。 |
int indexOf(Object o) | 返回对象o在List集合中第一次出现的位置索引。 |
int lastIndexOf(Object o) | 返回对象o在List集合中最后一次出现的位置索引。 |
Object remove(int index) | 删除并返回index索引处的元素。 |
Object set(int index,Object element) | 将index索引处的元素替换成element对象,返回新元素。 |
List subList(int fromIndex,int toIndex) | 返回从索引fromIndex(包含)到索引toIndex(不包含)处所有集合元素组成的子集合。List判断两个对象相等只要通过equals()方法比较返回true即可。 |
boolean isEmpty() | 返回集合是否为空。当集合长度为0时返回true,否则返回false。 |
Iterator iterator() | 返回一个Iterator对象,用于遍历集合里的元素。 |
boolean remove(Object o) | 删除集合中的指定元素o,当集合中包含了一个或多个元素o时,这些元素将被删除,该方法将返回true。 |
boolean removeAll(Collection c) | 从集合中删除集合c里包含的所有元素(相当于调用该方法的集合减集合c),如果删除了一个或一个以上的元素,该方法返回true。 |
boolean retainAll(Collection c) | 从集合中删除集合c里不包含的元素(相当于把调用该方法的集合变成该集合和集合c的交集),如果该操作改变了调用调用该方法的集合,则该方法返回true。 |
int size() | 该方法返回集合里元素的个数。 |
Object[] toArray() | 该方法把集合转换成一个数组,所有的集合元素变成对应的数组元素。 |
List接口中的contains是比较的内存地址。
注意,在使用contains之前,需要重写equals方法,例如:
public boolean equals(Object obj){if (obj instanceof VcubeRoomStatusPerson) {VcubeRoomStatusPerson vcubeRoomStatusPerson = (VcubeRoomStatusPerson) obj; return this.participantTag.equals(vcubeRoomStatusPerson.getParticipantTag()) && this.participantName.equals(vcubeRoomStatusPerson.getParticipantName())&& this.participantType.equals(vcubeRoomStatusPerson.getParticipantType()); }return super.equals(obj);
}
ArrayList
ArrayList是List接口的实现类,实现了可变大小的数组,
随机访问和遍历元素时,提供更好的性能。
ArrayList是线程不安全的,避免多线程环境下使用。
public class ArrayListDemo1 {public static void main(String[] args) {// 定义并创建一个ArrayList对象,list虽然允许存放不同类型的数据,但通常不建议这么做。List<Integer> list1 = new ArrayList<Integer>();// 判断list是否有元素System.out.println(list1.isEmpty());// 添加list元素list1.add(5);for (int i = 0; i < 5; i++) {list1.add(i);}list1.add(2);System.out.println(list1);// 从list获取下标为x的元素System.out.println(list1.get(1));// 如果list中有此元素则返回该元素的下标(从0开始),否则返回-1System.out.println("index==>" + list1.indexOf(2));// 如果list中有此元素则返回最后一次出现的该元素的下标(从0开始),否则返回-1System.out.println("index==>" + list1.lastIndexOf(2));// list中元素个数System.out.println("~~~" + list1.size() + "~~~");// 删除list元素,允许按下标删和按元素删两种方式list1.remove(new Integer(3));// 指定位置添加元素,效率低,因为会把大家都往后移动。。。。list1.add(0, 9);System.out.println(list1);// 指定位置添加元素,直接覆盖list1.set(0, 8);System.out.println(list1);// list转数组Integer[] xxx = list1.toArray(new Integer[] {});for (Integer a : xxx) {System.out.println("array===>" + a);}// list添加另外一个listList<Integer> list2 = new ArrayList<Integer>();list2.add(10);list2.add(11);list2.add(12);list1.addAll(list2);System.out.println(list1);// 切分出一个子list,类似于String的substring()List<Integer> subList1 = list1.subList(0, 3);System.out.println("subList1=" + subList1);// list中是否包含某个元素if (list1.contains(2)) {System.out.println("2 yes");} else {System.out.println("2 no");}// 注意,此处我删掉了list里的一个元素,这个元素原本是属于list2的,然后containsAll就失败了。list1.remove(new Integer(5));if (list1.containsAll(list2)) {System.out.println("list2 yes");} else {System.out.println("list2 no");}// 其实在list1中的list2已经不完整了,但是也能把剩余的全部干掉。list1.removeAll(list2);System.out.println(list1);list1.add(1);List<Integer> list3 = new ArrayList<Integer>();list3.add(1);// 只保留参数与list1的交集,即1;list是3,2,1,参数是1,则保留1。如果list是1,参数是3,2,1则返回false,没有变化。System.out.println(list1.retainAll(list3));System.out.println(list1);// 清空listlist1.clear();System.out.println(list1);// list的四种遍历方式List<String> list4 = new ArrayList<String>();list4.add("A");list4.add("B");list4.add("C");// 第1种使用foreach遍历Listfor (String str : list4) { //System.out.println(str);}// 第2种使用原始forfor (int i = 0; i < list4.size(); i++) {System.out.println(list4.get(i));}// 第3种使用迭代器进行相关遍历Iterator<String> ite = list4.iterator();while (ite.hasNext()) {System.out.println(ite.next());}// 第4种使用JDK8的Lambdalist4.forEach(item->System.out.println(item));}
}
LinkedList
LinkedList是List接口的实现类,
它是一个基于链表实现的List类,
对于顺序访问集合中的元素进行了优化,特别是插入,
删除元素的时候速度非常快,
但是随机访问集合元素时性能较差。
LinkedList既实现了List接口,也实现了Deque接口,
由于实现了Deque接口,可以被当成双端队列来使用,
也可以作为栈来使用。
该类实现了List接口,允许有null(空)元素。
主要用于创建链表数据结构,该类没有同步方法,
如果多个线程同时访问一个List,则必须自己实现访问同步,解决方法就是在创建List时候构造一个同步的List。
public class LinkedListDemo1 {public static void main(String[] args) {// 创建并初始化链表,LinkedList既可以当队列也可以当栈LinkedList<String> books = new LinkedList<>();// 加入到链表的头部books.push("a");// 加入到栈的尾部,注意此处不会因为写在前面就放在链表的前面books.offer("b");// 加入到链表的头部(最后加的放在链表的最上面)books.offerFirst("c");//加入到链表的尾部books.addLast("d");//加入到链表的尾部books.addLast("e");//加入到链表的尾部books.addLast("f");//从 头删除一个链表元素books.removeFirst();//从 尾删除一个链表元素books.removeLast();// 遍历链表for (int i = 0; i < books.size(); i++) {System.out.println(books.get(i));}// 访问但不删除栈顶的元素System.out.println(books.peekFirst());// 访问但不删除队列的最后一个元素System.out.println(books.peekLast());// 将栈顶的元素弹出栈System.out.println(books.pop());// 访问并删除队列的最后一个元素System.out.println(books);System.out.println(books.pollLast());System.out.println(books);System.out.println("----------");//可以给定一个Collection作为参数来创建链表List<String> list = new ArrayList<>();list.add("g");list.add("h");list.add("i");LinkedList<String> books2 = new LinkedList<>(list);System.out.println(books2);}
}
Vector
该类和ArrayList非常相似,但是该类是同步的,
可以用在多线程的情况,该类允许设置默认的增长长度,
默认扩容方式为原来的2倍。
Stack是Vector的一个子类,
它实现了一个标准的后进先出的栈。
未完待续
Map接口
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Azpm4HyA-1603362650512)(evernotecid://85A94EB2-9BD2-45DE-A16D-D9C9CD7ECF0B/appyinxiangcom/12192613/ENResource/p299)]
Map接口将唯一的键映射到值,用于存储[键/值]映射关系,
[键/值]=[key/value],使用key可以找到value,
例如:
key=5,value=user5对象;
key=6,value=user6对象;
方法 | 描述 |
---|---|
void clear() | 删除该Map对象中所有key-value对。 |
boolean containsKey(Object key) | 查询Map中是否包含指定的key,如果包含则返回true。 |
boolean containsValue(Object value) | 查询Map中是否包含一个或多个value,如果包含则返回true。 |
Set entrySet() | 返回Map中包含的key-value对所组成的Set集合,每个集合元素都是Map.Entry(Entry是Map的内部类)对象。 |
Object get(Object key) | 返回指定key所对应的value;如果此Map中不包含该key,则返回null。 |
boolean isEmpty() | 查询该Map是否为空(即不包含任何key-value对),如果为空则返回true。 |
Set keySet() | 返回该Map中所有key组成的Set集合。 |
Object put(Object key,Object value) | 添加一个key-value对,如果当前Map中已有一个与该key相等的key-value对,则新的key-value对会覆盖原来的key-value对。 |
void putAll(Map m) | 将指定Map中的key-value对复制到本Map中。 |
Object remove(Object key) | 删除指定key所对应的key-value对,返回被删除key所关联的value,如果该key不存在,则返回null。 |
int size() | 返回Map里的key-value对的个数。 |
Collection values() | 返回该Map里所有value组成的Collection。 |
Map中包含了一个内部类Entry,
Map.Entry,描述在一个Map中的一个元素(键/值对)。
该类封装了一个key-value对,方法如下:
方法 | 描述 |
---|---|
Object getKey() | 返回该Entry里包含的key值。 |
Object getValue() | 返回该Entry里包含的value值。 |
Object setValue(V value) | 设置该Entry里包含的value值,并返回新设置的value值。 |
HashMap
HashMap是一个散列表,实现了Map接口,
它存储的内容是键值对(key-value)映射,
key-value可为null,无序,性能较高,线程不安全。
HashMap查找数据非常快,
它并不是像ArrayList那样一个挨着一个的找,
而是使用[hash code/哈希码]来查找数据。
在HashMap的构造方法中,
可以设定hash表的capacity与load factor,
用来调节性能参数。
判断2个key是否相等,
也需要equals()+hashCode()双验证,
在使用containsValue()时,
只要2个对象通过equals()返回true即可判断。
public class HashMapDemo2 {public static void main(String[] args) {Map<String, String> map = new HashMap<String, String>();map.put("1", "value1");map.put("2", "value2");map.put("3", "value3");// 第一种:普遍使用,二次取值System.out.println("通过Map.keySet遍历key和value:");for (String key : map.keySet()) {System.out.println("key= " + key + " and value= " + map.get(key));}// 第二种System.out.println("通过Map.entrySet使用iterator遍历key和value:");Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();while (it.hasNext()) {Map.Entry<String, String> entry = it.next();System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());}// 第三种:推荐,尤其是容量大时System.out.println("通过Map.entrySet遍历key和value");for (Map.Entry<String, String> entry : map.entrySet()) {System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());}// 第四种System.out.println("通过Map.values()遍历所有的value,但不能遍历key");for (String v : map.values()) {System.out.println("value= " + v);}// 第五种JDK8map.forEach((k, v) -> {System.out.println(k + " " + v);});}
}
LinkedHashMap
LinkedHashMap使用双向链表,
来维护key-value对的顺序(其实只需要考虑key的顺序),
顺序与key-value对的插入顺序保持一致。
Map<String,Object> m = new LinkedHashMap();
//按顺序来的
m.put("1", 1);
m.put("2", 2);
m.put("3", 3);//遍历MAP
for (String key : m.keySet()) {System.out.println("key= "+ key + " and value= " + m.get(key));
}
注意:
在修改map里的数据的时候,如果修改完之后,
不再put,那就不会存上。
Hashtable
Hashtable是Dictionary(字典) 类的子类,
位于java.util包中。
Hashtable的元素不为null,无序,线程安全,
HashMap比Hashtable要快一点。
未完待续
TreeMap
TreeMap是基于红黑树数据结构的实现,
每个key-value对即作为红黑树的一个节点,
TreeMap存储key-value对(节点)时,
需要根据key对节点进行大小排序(比较顺序)。
TreeMap可以保证所有的key-value对处于有序状态,TreeMap有两种排序方式:
自然排序,TreeMap的所有key必须实现Comparable接口,而且所有的key应该是同一个类的对象;
定制排序:创建TreeMap时,传入一个Comparator对象,该对象负责对TreeMap中的所有key进行排序。采用定制排序时不要去Map的key实现Comparable接口;
TreeMap中判断2个key相等的标准是:
2个key通过compareTo()方法返回0,
如果key是自定义类,则需要重写equals方法,
让equals和compareTo保持一致。
SortedMap接口继承于Map接口,使Key保持在升序排列。
TreeMap比HashMap、Hashtable要慢,
尤其在插入,删除key-value对时更慢。
方法 | 描述 |
---|---|
Map.Entry firstEntry() | 返回该Map中最小key所对应的key-value对,如果该Map为空,则返回null。 |
Object firstKey() | 返回该Map中的最小key值,如果该Map为空,则返回null。 |
Map.Entry lastEntry() | 返回该Map中最大key所对应的key-value对,如果该Map为空或不存在这样的key-value对,则都返回null。 |
Object lastKey() | 返回该Map中的最大key值,如果该Map为空或不存在这样的key,则都返回null。 |
Map.Entry higherEntry(Object key) | 返回该Map中位于key后一位的key-value对(即大于指定key的最小key所对应的key-value对),如果该Map为空,则返回null。 |
Map.Entry lowEntry(Object key) | 返回该Map中位于key前一位的key-value对(即小于指定key的最大key所对应的key-value对),如果该Map为空,则返回null。 |
Object higherKey(Object key) | 返回该Map中位于key后一位的key值(即大于指定key的最小key值)。如果该Map为空或不存在这样的key-value对,则都返回null。 |
Object lowKey(Object key) | 返回该Map中位于key前一位的key值(即小于指定key的最大key值)。如果该Map为空或不存在这样的key-value对,则都返回null。 |
NavigableMap subMap(Object fromKey,boolean fromInclusive,Object toKey,boolean toInclusive) | 返回该Map的子Map,其key的范围是从fromKey(是否包括取决于第二个参数)到toKey(是否包括取决于第四个参数)。 |
SortedMap subMap(Object fromKey,Object toKey) | 返回该Map的子Map,其key的范围是从fromKey(包括)到toKey(不包括)。 |
SortedMap tailMap(Object fromKey) | 返回该Map的子Map,其key的范围是大于fromKey(包括)的所有key。 |
SortedMap headMap(Object toKey) | 返回该Map的子Map,其key的范围是小于toKey(不包括)的所有key。 |
NavigableMap tailMap(Object fromKey,boolean inclusive) | 返回该Map的子Map,其key的范围是大于fromKey(是否包括取决于第二个参数)的所有key。 |
NavigableMap headMap(Object toKey,boolean inclusive) | 返回该Map的子Map,其key的范围是小于toKey(是否包括取决于第二个参数)的所有key。 |
WeakHashMap
当某个对象在WeakHashMap中充当key时,
在其他地方都没有引用这个对象的话,
那么这个对象可能会被当做垃圾进行GC。
当GC回收了该key所对应的实际对象之后,
WeakHashMap会自动删除该key对应的key-value对。
IdentityHashMap
IdentityHashMap用而非equals()比较key,
当2个key严格相等(key1key2)时,
IdentityHashMap才认为2个key相等。
未完待续
EnumMap
EnumMap是一个与枚举类一起使用的Map实现,
EnumMap中的所有key都必须是单个枚举类的枚举值,
创建EnumMap时必须显式或者隐式指定它对应的枚举类。
EnumMap根据key的自然顺序,
即枚举值在枚举类中的定义顺序,来维护key-value对的顺序。
EnumMap不允许使用null作为key,但允许null作为value。
EnumMap的性能最好,但只能用于枚举值作为key。
Collections
排序操作:
方法 | 没事 |
---|---|
static void reverse(List list) | 反转指定List集合中元素的顺序。 |
static void shuffle(List list) | 对List集合元素进行随机排序。 |
static void sort(List list) | 根据元素的自然顺序对指定List集合的元素按升序进行排序。 |
static void sort(List list,Comparator c) | 根据指定Comparator产生的顺序对List集合元素进行排序。 |
static void swap(List list,int i,int j) | 将指定List集合中的i处元素和j处元素进行交换。 |
static void rotate(List list,int distance) | 当distance为正数时,将list集合的后distance个元素“整体”移到前面,当distance为负数时,将list集合的前distance个元素“整体”移到后面。该方法不会改变集合的长度。 |
查找,替换:
方法 | 描述 |
---|---|
static int binarySearch(List list,Object key) | 使用二分搜索法搜索指定的List集合,以获得指定对象在List集合中的索引。如果要使该方法可以正常工作,则必须保证List中的元素已经处于有序状态。 |
static Object max(Collection coll) | 根据元素的自然排序,返回给定集合中的最大元素。 |
static Object max(Collection coll,Comparator comp) | 根据Comparator指定的顺序,返回给定集合中的最大元素。 |
static Object min(Collection coll) | 根据元素的自然排序,返回给定集合中的最小元素。 |
static Object min(Collection coll,Comparator comp) | 根据Comparator指定的顺序,返回给定集合中的最小元素。 |
static void fill(List list,Object obj) | 使用指定元素obj替换指定List集合中的所有元素。 |
static int frequence(Collection c,Object o) | 返回指定集合中指定元素的出现次数。 |
static indexOfSubList(List source,List target) | 返回子List对象在父List对象中第一次出现的位置索引,如果父List中没有出现这样的子List,则返回-1。 |
static int lastIndexOfubList(List source,List target) | 返回子List对象在父List对象中最后一次出现的位置索引,如果父List中没有出现这样的子List,则返回-1。 |
static boolean replaceAll(List list,Object oldVal,Object newVal) | 使用一个新值newVal替换List对象的所有旧值oldVal。 |
同步控制:
Collections提供了多个synchronizedXXX()方法,
该方法可以将指定集合包装成线程同步的集合,
从而解决多线程并发访问集合时的线程安全问题。
例如
Collections.synchronizedSet(new HashSet());
设置不可变集合:
方法 | 描述 |
---|---|
emptyXXX() | 返回一个空的,不可变的集合对象,此处的集合既可以是List,也可以是Set,还可以是Map。 |
singletonXxx() | 返回一个只包含指定对象(只有一个或一项元素)的,不可变的集合对象,此处的集合既可以是List,也可以是Set,还可以是Map。 |
unmodifiableXXX() | 返回指定集合对象的不可变视图,此处的集合既可以是List,也可以是Set,还可以是Map。 |
上面三个方法可以生成出只读的Collection或Map。
总结
未完待续
明翰Java教学系列之集合框架篇V0.2(持续更新)相关推荐
- 明翰Java教学系列之进阶面向对象篇
复习 1.Java有多少种数据类型,数据类型的分类?数据类型的大小排序?默认类型?默认值? 2.Java的工作机制? 3.Java中有多少种初始化数组的方式? 4.什么是变量,如何定义变量?Java中 ...
- 明翰Java教学系列之认识Java篇V1.3(持续更新)
文章目录 传送门 前言 什么是Java? Java之父 `Java的应用场景` Java部分特点 Java工作机制 JDK(Java Development Kit) JRE(Java Runtime ...
- 明翰Java教学系列之多线程篇V0.2(持续更新)
文章目录 传送门 前言 背景知识 并行与并发 线程与进程 内存模型 1. 计算机内存模型 `2. Java内存模型` 2.1 内存交互 2.1.1 交互操作 2.1.2 交互规则 `2.2 并发编程特 ...
- 明翰英语教学系列之冠词篇
文章目录 前言 定冠词 定冠词的用法 1. `定冠词的特指用法` 1.1 `某个或者某些特定的人或物` 1.2 `上文提过的人或物(第二次提到)` 1.3 双方彼此都知道的人或物(默认) 1.4 形容 ...
- 明翰英语教学系列之方法篇
文章目录 传送门 前言 `学习路径&知识体系` 学习技巧 `构词规律` `词汇的偏旁部首` 词义前缀 否定前缀 `in-` mis- dis- de- un- con前缀 out前缀 sur前 ...
- 明翰英语教学系列之雅思阅读篇V0.9(持续更新)
文章目录 传送门 6. 阅读 READING 6.1 阅读评分标准 6.2 阅读题型 `6.2.1 阅读填空题` `摘要填空题(Summary)` `无选项摘要填空` 1. 找定位词 2. 确定答案词 ...
- 明翰英语教学系列之动词篇V0.3
文章目录 传送门 前言 1. 动词概念 2. `动词的分类` 2.1 按照功能分类 2.1.1 实义动词&行为动词 2.1.2 `系动词&联系动词` 系动词的分类 `状态系动词` `感 ...
- 明翰英语教学系列之数词篇V0.2(持续更新)
文章目录 传送门 什么是数词 基数词 基数词的单复数 序数词 数词应用 `表达[日期/时间]` 日期 年 月.日 年.月.日 `时间` 直接表达 间接表达 分数 小数 百分数 钱币 长度单位 重量单位 ...
- 明翰全日制英国硕士留学攻略V2.7(持续更新)
文章目录 传送门 前言 1. 留学准备 1.1 `留学原因` 1.2 选择国家 1.3 `选择中介` 1.4 `选择学校与专业` `offer` 1.4.1 预科 1.4.2 `1年制与2年制` 1. ...
最新文章
- 用Python分析了1w场吃鸡数据,原来吃鸡要这么玩!
- RH系列linux上编译android2.3(gingerbread)
- C++编程进阶2(编译器在类内默认生成的函数讨论以及纯虚析构函数)
- Sublime和Webstorm新建代码块
- js实现旋转木马轮播图
- java8 streams_另一个Java 8 Lamdbas和Streams示例
- 第76节:Java中的基础知识
- TelPhoneManager中的常用方法和状态获取
- 咦?Storyboard在WPF变换中怎么不能用了?
- Python_基于statsmodel包画Bland altman plot (Mean Difference Plot)用于预测结果分析
- Python Bug: TypeError: a bytes-like object is required, not ‘str
- 全网首发:怎样制作CDKEY(6)-CDKEY破解
- dsoframer.ocx java_dsoframer.ocx(java web 操作word) 总结一下
- 高等数学660---从214到221
- 写给大家看的量子力学——量子通信、量子隐形传输技术简介
- nodejs Log4js v2.x配置使用
- Bugzilla使用
- 腾讯云服务器怎么搭建多个ip,(技巧)利用腾讯云架设多ip实现单窗口单ip
- 前端基础(二):HTML之列表、表格、表单标签
- IOS手机安装旧版APP(不要问我为什么安装旧版,有的旧版功能更强大)