一、集合框架的概述

1.集合、数组都是对多个数据进行存储操作的结构,简称Java容器。
说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt,.jpg,.avi,数据库中)

2.1 数组在存储多个数据方面的特点:
> 一旦初始化以后,其长度就确定了。
> 数组一旦定义好,其元素的类型也就确定了。我们也就只能操作指定类型的数据了。
比如:String[] arr;int[] arr1;Object[] arr2;
2.2 数组在存储多个数据方面的缺点:
> 一旦初始化以后,其长度就不可修改。
> 数组中提供的方法非常有限,对于添加、删除、插入数据等操作,非常不便,同时效率不高。
> 获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用
> 数组存储数据的特点:有序、可重复。对于无序、不可重复的需求,不能满足。


二、集合框架


|——Collection接口:单列集合,用来存储一个一个的对象
|——List接口:存储有序的、可重复的数据。 —>“动态”数组
|——ArrayList、LinkedList、Vector

  1. |----Set接口:存储无序的、不可重复的数据 -->高中讲的“集合”<br /> |----HashSetLinkedHashSetTreeSet
  2. |----Map接口:双列集合,用来存储一对(key - value)一对的数据 -->高中函数:y = f(x)<br /> |----HashMapLinkedHashMapTreeMapHashtableProperties


三、Collection接口中的方法的使用

1、添加

add(Object obj)
addAll(Collection coll) :将coll集合中的元素添加到当前的集合中

2、获取有效元素的个数

int size()

3、清空集合

void clear()

4、是否是空集合

boolean isEmpty() :是空返回true,不是空返回false

  1. public void test1(){
  2. Collection coll = new ArrayList();
  3. //add(Object e):将元素e添加到集合coll中
  4. coll.add("AA");
  5. coll.add("BB");
  6. coll.add(123);//自动装箱
  7. coll.add(new Date());
  8. //size():获取添加的元素的个数
  9. System.out.println(coll.size());//4
  10. //addAll(Collection coll1):将coll1集合中的元素添加到当前的集合中
  11. Collection coll1 = new ArrayList();
  12. coll1.add(456);
  13. coll1.add("CC");
  14. coll.addAll(coll1);
  15. System.out.println(coll.size());//6
  16. System.out.println(coll);
  17. //clear():清空集合元素
  18. coll.clear();
  19. //isEmpty():判断当前集合是否为空
  20. System.out.println(coll.isEmpty());
  21. }

5、是否包含某个元素

boolean contains(Object obj):是通过元素的equals方法来判断是否是同一个对象
boolean containsAll(Collection c):也是调用元素的equals方法来比较的。拿两个集合的元素挨个比较。

  1. Collection coll = new ArrayList();
  2. coll.add(123);
  3. coll.add(456);
  4. // Person p = new Person("Jerry",20);
  5. // coll.add(p);
  6. coll.add(new Person("Jerry",20));
  7. coll.add(new String("Tom"));
  8. coll.add(false);
  1. boolean contains = coll.contains(123);
  2. System.out.println(contains);//true
  3. System.out.println(coll.contains(new String("Tom")));//true
  4. // System.out.println(coll.contains(p));//true
  5. System.out.println(coll.contains(new Person("Jerry",20)));//false -->true
  6. //Person中的equal()方法重写了,如果不重写应该为false,重写为true
  7. //2.containsAll(Collection coll1):判断形参coll1中的所有元素是否都存在于当前集合中。
  8. Collection coll1 = Arrays.asList(123,456);
  9. System.out.println(coll.containsAll(coll1));//true

6、删除

boolean remove(Object obj) :通过元素的equals方法判断是否是要删除的那个元素。只会删除找到的第一个元素
boolean removeAll(Collection coll):取当前集合的差集

  1. public void test2(){
  2. //3.remove(Object obj):从当前集合中移除obj元素。
  3. Collection coll = new ArrayList();
  4. coll.add(123);
  5. coll.add(456);
  6. coll.add(new Person("Jerry",20));
  7. coll.add(new String("Tom"));
  8. coll.add(false);
  9. coll.remove(1234);
  10. System.out.println(coll);//[123, 456, Person{name='Jerry', age=20}, Tom, false]
  11. coll.remove(new Person("Jerry",20));
  12. System.out.println(coll);//[123, 456, Tom, false]
  13. //4. removeAll(Collection coll1):差集:从当前集合中移除coll1中所有的元素。
  14. Collection coll1 = Arrays.asList(123,456);
  15. coll.removeAll(coll1);
  16. System.out.println(coll);//[Tom, false]
  17. }

7、取两个集合的交集

boolean retainAll(Collection c):把交集的结果存在当前集合中,不影响c

  1. Collection coll1 = Arrays.asList(123,456,789);
  2. coll.retainAll(coll1);
  3. System.out.println(coll);//[123, 456]

8、集合是否相等

boolean equals(Object obj)

  1. System.out.println(coll.equals(coll1));//false

9、转成对象数组

Object[] toArray()

  1. Object[] arr = coll.toArray();//已经是数组了
  2. for(int i = 0;i < arr.length;i++){
  3. System.out.println(arr[i]);
  4. }

拓展:数组 —->集合:调用Arrays类的静态方法asList()

  1. List<String> list = Arrays.asList(new String[]{"AA", "BB", "CC"});
  2. System.out.println(list);//[AA, BB, CC]
  3. List arr1 = Arrays.asList(new int[]{123, 456});
  4. System.out.println(arr1.size());//1
  5. List arr2 = Arrays.asList(new Integer[]{123, 456});
  6. System.out.println(arr2.size());//2

10、获取集合对象的哈希值

hashCode()

  1. System.out.println(coll.hashCode());//-1200490100

11、遍历 (集合)

iterator():返回迭代器对象,用于集合遍历

集合元素的遍历操作,使用迭代器Iterator接口
1)内部的方法:hasNext() 和 next()
2)集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。
3)内部定义了remove(),可以在遍历的时候,删除集合中的元素。此方法不同于集合直接调用remove()

  1. public void test1(){
  2. Collection coll = new ArrayList();
  3. coll.add(123);
  4. coll.add(456);
  5. coll.add(new Person("Jerry",20));
  6. coll.add(new String("Tom"));
  7. coll.add(false);
  8. Iterator iterator = coll.iterator();
  9. ////hasNext():判断是否还有下一个元素
  10. while(iterator.hasNext()){
  11. //next():①指针下移 ②将下移以后集合位置上的元素返回
  12. System.out.println(iterator.next());
  13. }
  14. //错误方式二:
  15. //集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。
  16. while (coll.iterator().hasNext()){
  17. System.out.println(coll.iterator().next());
  18. }
  19. //删除集合中"Tom"
  20. Iterator iterator = coll.iterator();
  21. while (iterator.hasNext()){
  22. Object obj = iterator.next();
  23. if("Tom".equals(obj)){
  24. iterator.remove();
  25. }
  26. }
  27. //遍历集合
  28. iterator = coll.iterator();//让指针从头开始
  29. while (iterator.hasNext()){
  30. System.out.println(iterator.next());
  31. }
  32. }

增强for循环

jdk 5.0 新增了foreach循环,用于遍历集合、数组
for(集合元素的类型 局部变量 : 集合对象)
内部仍然调用了迭代器。本质上是一样的

  1. public class ForTest {
  2. @Test
  3. public void test1(){
  4. Collection coll = new ArrayList();
  5. coll.add(123);
  6. coll.add(456);
  7. coll.add(new Person("Jerry",20));
  8. coll.add(new String("Tom"));
  9. coll.add(false);
  10. //for(集合元素的类型 局部变量 : 集合对象)
  11. //内部仍然调用了迭代器。
  12. for(Object obj : coll){
  13. System.out.println(obj);
  14. }
  15. }
  16. @Test
  17. public void test2(){
  18. int[] arr = new int[]{1,2,3,4,5,6};
  19. //for(数组元素的类型 局部变量 : 数组对象)
  20. for(int i : arr){
  21. System.out.println(i);
  22. }
  23. }
  24. }

练习题
  1. //练习题
  2. @Test
  3. public void test3(){
  4. String[] arr = new String[]{"MM","MM","MM"};
  5. // //方式一:普通for赋值
  6. // for(int i = 0;i < arr.length;i++){
  7. // arr[i] = "GG";
  8. // }
  9. //方式二:增强for循环
  10. for(String s : arr){
  11. s = "GG";//不会更改原有数组
  12. }
  13. for(int i = 0;i < arr.length;i++){
  14. System.out.println(arr[i]);
  15. }//方式一更改为GG,方式二仍为MM
  16. }

四、 List接口

1. List接口框架


|——Collection接口:单列集合,用来存储一个一个的对象
|——List接口:存储有序的、可重复的数据。 —>“动态”数组,替换原有的数组
|——ArrayList:作为List接口的主要实现类;线程不安全的,效率高;底层使用Object[] elementData存储
|——LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高;底层使用双向链表存储
|——Vector:作为List接口的古老实现类;线程安全的,效率低;底层使用Object[] elementData存储


2. ArrayList的源码分析:

2.1 jdk 7情况下

  1. ArrayList list = new ArrayList();//底层创建了长度是10的Object[]数组elementData
  2. list.add(123);//elementData[0] = new Integer(123);
  3. ...
  4. list.add(11);//如果此次的添加导致底层elementData数组容量不够,则扩容。
  5. // 默认情况下,扩容为原来的容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中。

结论:建议开发中使用带参的构造器:ArrayList list = new ArrayList(int initialCapacity)

  1. public ArrayList(int initialCapacity) {
  2. if (initialCapacity > 0) {
  3. this.elementData = new Object[initialCapacity];//构建数组
  4. } else if (initialCapacity == 0) {
  5. this.elementData = EMPTY_ELEMENTDATA;
  6. } else {
  7. throw new IllegalArgumentException("Illegal Capacity: "+
  8. initialCapacity);
  9. }
  10. }


2.2 jdk 8中ArrayList的变化:


ArrayList list = new ArrayList();//底层Object[] elementData初始化为{}.并没有创建长度为10的数组

list.add(123);//第一次调用add()时,底层才创建了长度10的数组,并将数据123添加到elementData[0]

后续的添加和扩容操作与jdk 7 无异。

2.3 小结:

jdk7中的ArrayList的对象的创建类似于单例的饿汉式,而jdk8中的ArrayList的对象的创建类似于单例的懒汉式,延迟了数组的创建,节省内存。

3. LinkedList的源码分析

LinkedList list = new LinkedList(); 内部声明了Node类型的first和last属性,默认值为null
list.add(123);//将123封装到Node中,创建了Node对象。

其中,Node定义为:体现了LinkedList的双向链表的说法

  1. private static class Node<E> {
  2. E item;
  3. Node<E> next;
  4. Node<E> prev;
  5. Node(Node<E> prev, E element, Node<E> next) {
  6. this.item = element;
  7. this.next = next;
  8. this.prev = prev;
  9. }
  10. }


4. Vector的源码分析:

jdk7和jdk8中通过Vector()构造器创建对象时,底层都创建了长度为10的数组。
在扩容方面,默认扩容为原来的数组长度的2倍。

面试题:ArrayList、LinkedList、Vector三者的异同?
同:三个类都是实现了List接口,存储数据的特点相同:存储有序的、可重复的数据
不同:见上


5. List接口中的常用方法

void add(int index, Object ele):在index位置插入ele元素
boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
Object get(int index):获取指定index位置的元素
int indexOf(Object obj):返回obj在集合中首次出现的位置
int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
Object remove(int index):移除指定index位置的元素,并返回此元素
Object set(int index, Object ele):设置指定index位置的元素为ele
List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合

总结:常用方法
增:add(Object obj)
删:remove(int index) / remove(Object obj)
改:set(int index, Object ele)
查:get(int index)
插:add(int index, Object ele)
长度:size()
遍历:① Iterator迭代器方式② 增强for循环 ③ 普通的循环

  1. public void test1(){
  2. ArrayList list = new ArrayList();
  3. list.add(123);
  4. list.add(456);
  5. list.add("AA");
  6. list.add(new Person("Tom",12));
  7. list.add(456);
  8. System.out.println(list);
  9. //void add(int index, Object ele):在index位置插入ele元素
  10. list.add(1,"BB");
  11. System.out.println(list);
  12. //boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
  13. List list1 = Arrays.asList(1, 2, 3);//aslist是数组转集合
  14. list.addAll(list1);
  15. // list.add(list1);
  16. System.out.println(list.size());//9
  17. //Object get(int index):获取指定index位置的元素
  18. System.out.println(list.get(0));
  19. //int indexOf(Object obj):返回obj在集合中首次出现的位置。如果不存在,返回-1.
  20. int index = list.indexOf(4567);
  21. System.out.println(index);
  22. //int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置。如果不存在,返回-1.
  23. System.out.println(list.lastIndexOf(456));
  24. //Object remove(int index):移除指定index位置的元素,并返回此元素
  25. Object obj = list.remove(0);
  26. System.out.println(obj);
  27. System.out.println(list);
  28. //Object set(int index, Object ele):设置指定index位置的元素为ele
  29. list.set(1,"CC");
  30. System.out.println(list);
  31. //List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的左闭右开区间的子集合
  32. List subList = list.subList(2, 4);
  33. System.out.println(subList);
  34. System.out.println(list);
  35. //方式一:Iterator迭代器方式
  36. Iterator iterator = list.iterator();
  37. while(iterator.hasNext()){
  38. System.out.println(iterator.next());
  39. }
  40. System.out.println("***************");
  41. //方式二:增强for循环
  42. for(Object obj : list){
  43. System.out.println(obj);
  44. }
  45. System.out.println("***************");
  46. //方式三:普通for循环
  47. for(int i = 0;i < list.size();i++){
  48. System.out.println(list.get(i));
  49. }
  50. }

面试题

  1. public class ListExer {
  2. /*
  3. 区分List中remove(int index)和remove(Object obj)
  4. */
  5. @Test
  6. public void testListRemove() {
  7. List list = new ArrayList();
  8. list.add(1);
  9. list.add(2);
  10. list.add(3);
  11. updateList(list);
  12. System.out.println(list);//[1, 3]
  13. }
  14. private void updateList(List list) {
  15. // list.remove(2);//这是删除了第二个位置,返回3,[1, 2]
  16. list.remove(new Integer(2));//删除了2,返回true,[1, 3]
  17. }
  18. }

五、set接口

1. Set接口的框架:

|——Collection接口:单列集合,用来存储一个一个的对象
|——Set接口:存储无序的、不可重复的数据 —>高中讲的“集合”
|——HashSet:作为Set接口的主要实现类;线程不安全的;可以存储null值
|——LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历
对于频繁的遍历操作,LinkedHashSet效率高于HashSet.
|——TreeSet:可以按照添加对象的指定属性,进行排序。

1) Set接口中没有额外定义新的方法,使用的都是Collection中声明过的方法。
2)要求:向Set(主要指:HashSet、LinkedHashSet)中添加的数据,其所在的类一定要重写hashCode()和equals()
要求:重写的hashCode()和equals()尽可能保持一致性:相等的对象必须具有相等的散列码
重写两个方法的小技巧:对象中用作 equals() 方法比较的 Field,都应该用来计算 hashCode 值。通常参与计算hashCode的对象的属性也应该参与到equals()中进行计算

2、HashSet

Set:存储无序的、不可重复的数据
以HashSet为例说明:
1. 无序性:不等于随机性。存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值决定的。
2. 不可重复性:保证添加的元素按照equals()判断时,不能返回true.即:相同的元素只能添加一个。

二、添加元素的过程:以HashSet为例:
我们向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值,
此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(即为:索引位置),判断
数组此位置上是否已经有元素:
如果此位置上没有其他元素,则元素a添加成功。 —->情况1
如果此位置上有其他元素b(或以链表形式存在的多个元素),则比较元素a与元素b的hash值:
如果hash值不相同,则元素a添加成功。—->情况2
如果hash值相同,进而需要调用元素a所在类的equals()方法:
equals()返回true,元素a添加失败
equals()返回false,则元素a添加成功。—->情况3

  1. 对于添加成功的情况2和情况3而言:元素a 与已经存在指定索引位置上数据以链表的方式存储。<br /> jdk 7 :元素a放到数组中,指向原来的元素。<br /> jdk 8 :原来的元素在数组中,指向元素a<br /> 总结:七上八下<br /> HashSet底层:数组+链表的结构。

3、LinkedHashSet的使用

LinkedHashSet作为HashSet的子类,在添加数据的同时,每个数据还维护了两个引用,记录此数据前一个
数据和后一个数据。(可以顺序遍历)
优点:对于频繁的遍历操作,LinkedHashSet效率高于HashSet

  1. public void test2(){
  2. Set set = new LinkedHashSet();
  3. set.add(456);
  4. set.add(123);
  5. set.add(123);
  6. set.add("AA");
  7. set.add("CC");
  8. set.add(new User("Tom",12));
  9. set.add(new User("Tom",12));
  10. set.add(129);
  11. Iterator iterator = set.iterator();
  12. while(iterator.hasNext()){
  13. System.out.println(iterator.next());
  14. }
  15. }

4、TreeSet

1.向TreeSet中添加的数据,要求是相同类的对象。
2.两种排序方式:自然排序(实现Comparable接口) 和 定制排序(Comparator)
3.自然排序中,比较两个对象是否相同的标准为:compareTo()返回0.不再是equals().

  1. //public class User implements Comparable
  2. //按照姓名从大到小排列,年龄从小到大排列
  3. @Override
  4. public int compareTo(Object o) {
  5. if(o instanceof User){
  6. User user = (User)o;
  7. // return -this.name.compareTo(user.name);
  8. int compare = -this.name.compareTo(user.name);
  9. if(compare != 0){
  10. return compare;
  11. }else{
  12. return Integer.compare(this.age,user.age);
  13. }
  14. }else{
  15. throw new RuntimeException("输入的类型不匹配");
  16. }
  17. }
  1. public void test1(){
  2. TreeSet set = new TreeSet();
  3. //失败:不能添加不同类的对象
  4. // set.add(123);
  5. // set.add(456);
  6. // set.add("AA");
  7. // set.add(new User("Tom",12));
  8. //举例一:
  9. // set.add(34);
  10. // set.add(-34);
  11. // set.add(43);
  12. // set.add(11);
  13. // set.add(8);
  14. //举例二:
  15. set.add(new User("Tom",12));
  16. set.add(new User("Jerry",32));
  17. set.add(new User("Jim",2));
  18. set.add(new User("Mike",65));
  19. set.add(new User("Jack",33));
  20. set.add(new User("Jack",56));
  21. Iterator iterator = set.iterator();
  22. while(iterator.hasNext()){
  23. System.out.println(iterator.next());
  24. }
  25. }


4.定制排序中,比较两个对象是否相同的标准为:compare()返回0.不再是equals().

  1. public void test2(){
  2. Comparator com = new Comparator() {
  3. //按照年龄从小到大排列
  4. @Override
  5. public int compare(Object o1, Object o2) {
  6. if(o1 instanceof User && o2 instanceof User){
  7. User u1 = (User)o1;
  8. User u2 = (User)o2;
  9. return Integer.compare(u1.getAge(),u2.getAge());
  10. }else{
  11. throw new RuntimeException("输入的数据类型不匹配");
  12. }
  13. }
  14. };
  15. TreeSet set = new TreeSet(com);
  16. set.add(new User("Tom",12));
  17. set.add(new User("Jerry",32));
  18. set.add(new User("Jim",2));
  19. set.add(new User("Mike",65));
  20. set.add(new User("Mary",33));
  21. set.add(new User("Jack",33));
  22. set.add(new User("Jack",56));
  23. Iterator iterator = set.iterator();
  24. while(iterator.hasNext()){
  25. System.out.println(iterator.next());
  26. }
  27. }

六、Map接口


1、Map的实现类的结构:


|——Map:双列数据,存储key-value对的数据 —-类似于高中的函数:y = f(x)
|——HashMap:作为Map的主要实现类;线程不安全的,效率高;存储null的key和value
|——LinkedHashMap:保证在遍历map元素时,可以按照添加的顺序实现遍历。
原因:在原有的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。
对于频繁的遍历操作,此类执行效率高于HashMap。
|——TreeMap:保证按照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序
底层使用红黑树
|——Hashtable:作为古老的实现类;线程安全的,效率低;不能存储null的key和value
|——Properties:常用来处理配置文件。key和value都是String类型

  1. HashMap的底层:数组+链表 jdk7及之前)<br /> 数组+链表+红黑树 jdk 8_<br /> 面试题:<br /> 1. HashMap的底层实现原理?<br /> 2. HashMap Hashtable的异同?<br /> 3. CurrentHashMap Hashtable的异同?(暂时不讲)


2、Map结构的理解:

1)Map中的key:无序的、不可重复的,使用Set存储所有的key —-> key所在的类要重写equals()和hashCode() (以HashMap为例)
2)Map中的value:无序的、可重复的,使用Collection存储所有的value —->value所在的类要重写equals()一个键值对:key-value构成了一个Entry对象。
3) Map中的entry:无序的、不可重复的,使用Set存储所有的entry


3、HashMap的底层实现原理?

1)以jdk7为例说明:


HashMap map = new HashMap():
在实例化以后,底层创建了长度是16的一维数组Entry[] table。
…可能已经执行过多次put…
map.put(key1,value1):
首先,调用key1所在类的hashCode()计算key1哈希值,此哈希值经过某种算法计算以后,得到在Entry数组中的存放位置。
如果此位置上的数据为空,此时的key1-value1添加成功。 ——情况1
如果此位置上的数据不为空,(意味着此位置上存在一个或多个数据(以链表形式存在)),比较key1和已经存在的一个或多个数据
的哈希值:
如果key1的哈希值与已经存在的数据的哈希值都不相同,此时key1-value1添加成功。——情况2
如果key1的哈希值和已经存在的某一个数据(key2-value2)的哈希值相同,继续比较:调用key1所在类的equals(key2)方法,比较:
如果equals()返回false:此时key1-value1添加成功。——情况3
如果equals()返回true:使用value1替换value2。

补充:关于情况2和情况3:此时key1-value1和原来的数据以链表的方式存储。

在不断的添加过程中,会涉及到扩容问题,当超出临界值(且要存放的位置非空)时,扩容。默认的扩容方式:扩容为原来容量的2倍,并将原有的数据复制过来。

2) jdk8 相较于jdk7在底层实现方面的不同:


1. new HashMap():底层没有创建一个长度为16的数组
2. jdk 8底层的数组是:Node[],而非Entry[]
3. 首次调用put()方法时,底层创建长度为16的数组
4. jdk7底层结构只有:数组+链表。jdk8中底层结构:数组+链表+红黑树。
4.1 形成链表时,七上八下(jdk7:新的元素指向旧的元素。jdk8:旧的元素指向新的元素)
4.2 当数组的某一个索引位置上的元素以链表形式存在的数据个数 > 8 且当前数组的长度 > 64时,此时此索引位置上的所数据改为使用红黑树存储。

DEFAULT_INITIAL_CAPACITY : HashMap的默认容量,16
DEFAULT_LOAD_FACTOR:HashMap的默认加载因子:0.75
threshold:扩容的临界值,=容量填充因子:16*0.75 => 12
TREEIFY_THRESHOLD:Bucket中链表长度大于该默认值,转化为红黑树:8
MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量:64


4、LinkedHashMap的底层实现原理(了解)//先后顺序

  1. // 源码中:
  2. static class Entry<K,V> extends HashMap.Node<K,V> {
  3. Entry<K,V> before, after;//能够记录添加的元素的先后顺序
  4. Entry(int hash, K key, V value, Node<K,V> next) {
  5. super(hash, key, value, next);
  6. }
  7. }

5、Map中定义的方法:


1)添加、删除、修改操作:


Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
void putAll(Map m):将m中的所有key-value对存放到当前map中
Object remove(Object key):移除指定key的key-value对,并返回value
void clear():清空当前map中的所有数据

  1. public void test3(){
  2. Map map = new HashMap();
  3. //添加
  4. map.put("AA",123);
  5. map.put(45,123);
  6. map.put("BB",56);
  7. //修改
  8. map.put("AA",87);
  9. System.out.println(map);//{AA=87, BB=56, 45=123}
  10. Map map1 = new HashMap();
  11. map1.put("CC",123);
  12. map1.put("DD",123);
  13. map.putAll(map1);
  14. System.out.println(map);//{AA=87, BB=56, CC=123, DD=123, 45=123}
  15. //remove(Object key)
  16. Object value = map.remove("CC");
  17. System.out.println(value);//123
  18. System.out.println(map);//{AA=87, BB=56, DD=123, 45=123}
  19. //clear()
  20. map.clear();//与map = null操作不同
  21. System.out.println(map.size());//0
  22. System.out.println(map);//{}
  23. }


2)元素查询的操作:

Object get(Object key):获取指定key对应的value
boolean containsKey(Object key):是否包含指定的key
boolean containsValue(Object value):是否包含指定的value
int size():返回map中key-value对的个数
boolean isEmpty():判断当前map是否为空
boolean equals(Object obj):判断当前map和参数对象obj是否相等

  1. public void test4(){
  2. Map map = new HashMap();
  3. map.put("AA",123);
  4. map.put(45,123);
  5. map.put("BB",56);
  6. // Object get(Object key)
  7. System.out.println(map.get(45));//123
  8. //containsKey(Object key)
  9. boolean isExist = map.containsKey("BB");
  10. System.out.println(isExist);//true
  11. isExist = map.containsValue(123);
  12. System.out.println(isExist);//true
  13. map.clear();
  14. System.out.println(map.isEmpty());//true
  15. }

3)元视图操作的方法:

Set keySet():返回所有key构成的Set集合
Collection values():返回所有value构成的Collection集合
Set entrySet():返回所有key-value对构成的Set集合

  1. public void test5(){
  2. Map map = new HashMap();
  3. map.put("AA",123);
  4. map.put(45,1234);
  5. map.put("BB",56);
  6. //遍历所有的key集:keySet()
  7. Set set = map.keySet();
  8. Iterator iterator = set.iterator();
  9. while(iterator.hasNext()){
  10. System.out.println(iterator.next());
  11. }
  12. System.out.println();
  13. //遍历所有的value集:values()
  14. Collection values = map.values();
  15. for(Object obj : values){
  16. System.out.println(obj);
  17. }
  18. System.out.println();
  19. //遍历所有的key-value
  20. //方式一:entrySet()
  21. Set entrySet = map.entrySet();
  22. Iterator iterator1 = entrySet.iterator();
  23. while (iterator1.hasNext()){
  24. Object obj = iterator1.next();
  25. //entrySet集合中的元素都是entry
  26. Map.Entry entry = (Map.Entry) obj;
  27. System.out.println(entry.getKey() + "---->" + entry.getValue());
  28. }
  29. System.out.println();
  30. //方式二:
  31. Set keySet = map.keySet();
  32. Iterator iterator2 = keySet.iterator();
  33. while(iterator2.hasNext()){
  34. Object key = iterator2.next();
  35. Object value = map.get(key);
  36. System.out.println(key + "=====" + value);
  37. }
  38. }

4)总结:常用方法:

添加:put(Object key,Object value)
删除:remove(Object key)
修改:put(Object key,Object value)
查询:get(Object key)
长度:size()
遍历:keySet() / values() / entrySet()

6、TreeMap

向TreeMap中添加key-value,要求key必须是由同一个类创建的对象
因为要按照key进行排序:自然排序 、定制排序

1)自然排序

  1. //自然排序
  2. @Test
  3. public void test1(){
  4. TreeMap map = new TreeMap();
  5. User u1 = new User("Tom",23);
  6. User u2 = new User("Jerry",32);
  7. User u3 = new User("Jack",20);
  8. User u4 = new User("Rose",18);
  9. map.put(u1,98);
  10. map.put(u2,89);
  11. map.put(u3,76);
  12. map.put(u4,100);
  13. Set entrySet = map.entrySet();
  14. Iterator iterator1 = entrySet.iterator();
  15. while (iterator1.hasNext()){
  16. Object obj = iterator1.next();
  17. Map.Entry entry = (Map.Entry) obj;
  18. System.out.println(entry.getKey() + "---->" + entry.getValue());
  19. }
  20. }

2) 定制排序:就是需要重写compare写

  1. //定制排序
  2. @Test
  3. public void test2(){
  4. TreeMap map = new TreeMap(new Comparator() {
  5. @Override
  6. public int compare(Object o1, Object o2) {
  7. if(o1 instanceof User && o2 instanceof User){
  8. User u1 = (User)o1;
  9. User u2 = (User)o2;
  10. return Integer.compare(u1.getAge(),u2.getAge());
  11. }
  12. throw new RuntimeException("输入的类型不匹配!");
  13. }
  14. });
  15. User u1 = new User("Tom",23);
  16. User u2 = new User("Jerry",32);
  17. User u3 = new User("Jack",20);
  18. User u4 = new User("Rose",18);
  19. map.put(u1,98);
  20. map.put(u2,89);
  21. map.put(u3,76);
  22. map.put(u4,100);
  23. Set entrySet = map.entrySet();
  24. Iterator iterator1 = entrySet.iterator();
  25. while (iterator1.hasNext()){
  26. Object obj = iterator1.next();
  27. Map.Entry entry = (Map.Entry) obj;
  28. System.out.println(entry.getKey() + "---->" + entry.getValue());
  29. }
  30. }

7、Properties

常用来处理配置文件。key和value都是String类型
image.png
image.png

  1. Properties pros = new Properties();
  2. fis = new FileInputStream("jdbc.properties");
  3. pros.load(fis);//加载流对应的文件
  4. String name = pros.getProperty("name");
  5. String password = pros.getProperty("password");
  6. System.out.println("name = " + name + ", password = " + password);

image.png

七、 Collections工具类

1、概念

Collections 是一个操作 Set、List 和 Map 等集合的工具类
Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作, 还提供了对集合对象设置不可变、对集合对象实现同步控制等方法

2、方法(静态)

reverse(List):反转 List 中元素的顺序
shuffle(List):对 List 集合元素进行随机排序(随机化,即打乱集合)
sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
Object min(Collection)
Object min(Collection,Comparator)

  1. List list = new ArrayList();
  2. list.add(123);
  3. list.add(43);
  4. list.add(765);
  5. list.add(-97);
  6. list.add(0);
  7. System.out.println(list);//[123, 43, 765, -97, 0]
  8. Collections.reverse(list);
  9. System.out.println(list);//[0, -97, 765, 43, 123]
  10. Collections.shuffle(list);
  11. System.out.println(list);//[123, -97, 43, 765, 0]
  12. Collections.shuffle(list);
  13. System.out.println(list);//[123, 0, 43, 765, -97]
  14. Collections.sort(list);
  15. System.out.println(list);//[-97, 0, 43, 123, 765]
  16. Collections.swap(list,0,1);
  17. System.out.println(list);//[0, -97, 43, 123, 765]
  18. Comparable a =Collections.max(list);
  19. System.out.println(a);//765


int frequency(Collection,Object):返回指定集合中指定元素的出现次数

  1. int frequency = Collections.frequency(list, 123);
  2. System.out.println(list);//[0, -97, 43, 123, 765]
  3. System.out.println(frequency);//1


void copy(List dest,List src):将src中的内容复制到dest中

  1. //报异常:IndexOutOfBoundsException("Source does not fit in dest")
  2. // List dest = new ArrayList();
  3. // Collections.copy(dest,list);
  4. //正确的:让列表长度一致
  5. List dest = Arrays.asList(new Object[list.size()]);
  6. System.out.println(dest.size());//list.size();
  7. Collections.copy(dest,list);
  8. System.out.println(dest);


boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值

  1. System.out.println(list);//[123, 43, 765, 765, 765, -97, 0]
  2. Collections.replaceAll(list,765,615);
  3. System.out.println(list);//[123, 43, 615, 615, 615, -97, 0]

3、Collections常用方法:同步控制

  1. /* Collections 类中提供了多个 synchronizedXxx() 方法,
  2. 该方法可使将指定集合包装成线程同步的集合,从而可以解决
  3. 多线程并发访问集合时的线程安全问题
  4. */
  5. //返回的list1即为线程安全的List
  6. List list1 = Collections.synchronizedList(list);

image.png