• 第十一章:Java集合


    目录

    十一:Java集合

    11.1:java集合框架概述

    11.2:Collection接口方法

    11.3:Iterator迭代器接口

    11.4:Collection子接口一:List

    11.5:Collection子接口二:Set

    11.6:Map接口

    11.7:Collections工具类

    11.8:增强for循环


    十一:Java集合

    11.1:java集合框架概述


            Java集合可以分为Collection和Map两种体系

                    Collection接口:单列数据,定义了存取一组对象的方法的集合

                            List:元素有序、可重复的集合

                            Set:元素无序、不可重复的集合

                    Map接口:双列数据,保存具有映射关系"key-value对"的集合

    11.2:Collection接口方法


    1. package com.jiayifeng.java;
    2. import org.junit.Test;
    3. import java.util.*;
    4. /**
    5. * author 爱编程的小贾
    6. * create 2023-09-19 15:34
    7. *
    8. * 一:集合框架的概述
    9. * 1.集合、数组都是对多个数据进行存储操作的结构,简称Java容器
    10. * 说明:此时的存储,主要指的是内存层面的存储,不涉及持久化的存储(.txt,
    11. * .jpg,.avi,数据库中)
    12. *
    13. * 2.数组在存储多个数据方面的特点:
    14. * ①一旦初始化后,其长度就确定了
    15. * ②一旦定义好后,其元素的类型就确定了,我们也就只能操作指定类型的数据了
    16. *
    17. * 3.数组在存储多个数据方面的缺点:
    18. * ①一旦初始化后,其长度就不可以修改
    19. * ②数组中提供的方法非常有限,对于添加、删除、插入数据等操作,非常不便,
    20. * 同时效率不高
    21. * ③获取数组中实际元素的个数的需求,数组没有现成的属性或方法可以调用
    22. * ④数组存储数据的特点:有序、可重复。对于无序、不可重复的需求,不可满足
    23. *
    24. * 二:集合框架
    25. * |----Collection接口:单列集合,用来存储一个一个的对象
    26. * |----List接口:存储有序的、可重复的数据 ->"动态"数组
    27. * |----ArrayList、LinkedList、Vector
    28. * |----Set接口:存储无序的、不可重复的数据 ->高中讲的“集合”
    29. * |----HashSet、LinkedHashSet、TreeSet
    30. *
    31. * |----Map接口:双列集合,用来存储一对一对的数据 ->高中函数:y = f(x)
    32. * |----HashMap、LinkedHashMap、TreeMap、HashTable、Properties
    33. *
    34. * 三:Collection接口中方法的使用
    35. * 向Collection接口的实现类的对象中添加数据obj时,要求obj所在类要重写equals()
    36. *
    37. */
    38. public class CollectionTest {
    39. @Test
    40. public void test() {
    41. Collection coll = new ArrayList();
    42. // add(Object e):将元素e添加到集合coll中
    43. coll.add("AA");
    44. coll.add("BB");
    45. coll.add("123");//自动装箱
    46. coll.add(new Date());
    47. // size():获取添加的元素的个数
    48. System.out.println(coll.size());//4
    49. // addAll(Collection coll1):将coll1集合中的元素添加到当前的集合中
    50. Collection coll1 = new ArrayList();
    51. coll1.add(456);
    52. coll1.add("CC");
    53. coll.addAll(coll1);
    54. System.out.println(coll.size());//6
    55. System.out.println(coll);//[AA, BB, 123, Tue Sep 19 16:19:49 CST 2023, 456, CC]
    56. // clear():清空集合元素
    57. coll.clear();
    58. // isEmpty():判断当前集合是否为空
    59. System.out.println(coll.isEmpty());//true
    60. }
    61. @Test
    62. public void test1(){
    63. Collection coll = new ArrayList();
    64. coll.add(123);
    65. coll.add(456);
    66. coll.add(new String());
    67. coll.add(false);
    68. coll.add(new Person("Jerry",20));
    69. // contains(Object obj):判断当前集合中是否包含obj
    70. // 我们在判断时会调用obj对象所在类的equals()
    71. boolean contains = coll.contains(123);
    72. System.out.println(contains);//true
    73. System.out.println(coll.contains(new String()));//false
    74. System.out.println(coll.contains(new Person("Jerry",20)));//false->true
    75. // containsAll(Collection coll1):判断形参coll1中所有元素是否都存在于当前集合中
    76. Collection coll1 = Arrays.asList(123,456);
    77. System.out.println(coll.containsAll(coll1));//true
    78. }
    79. @Test
    80. public void test2() {
    81. Collection coll = new ArrayList();
    82. coll.add(123);
    83. coll.add(456);
    84. coll.add(new Person("Jerry", 20));
    85. coll.add(new String());
    86. coll.add(false);
    87. // remove(Object obj):从当前集合中移除obj元素
    88. coll.remove(123);
    89. System.out.println(coll);
    90. // removeAll(Collection coll1):从当前集合中移除coll1中所有的元素
    91. Collection coll1 = Arrays.asList(123, 456);
    92. coll.removeAll(coll1);
    93. System.out.println(coll);
    94. }
    95. @Test
    96. public void test3(){
    97. Collection coll = new ArrayList();
    98. coll.add(123);
    99. coll.add(456);
    100. coll.add(new Person("Jerry",20));
    101. // coll.add(new String());
    102. coll.add(false);
    103. // retainAll(Collection coll1):交集:获取当前集合和coll1集合的交集,并返回给当前集合
    104. // Collection coll1 = Arrays.asList(123,456,789);
    105. // coll.retainAll(coll1);
    106. // System.out.println(coll);//[123, 456]
    107. // equals(Object obj):判断当前集合和形参集合的元素是否相同,若相同,则返回true
    108. Collection coll1 = new ArrayList();
    109. coll1.add(123);
    110. coll1.add(456);
    111. coll1.add(new Person("Jerry",20));
    112. // coll1.add(new String());
    113. coll1.add(false);
    114. System.out.println(coll.equals(coll1));//true
    115. }
    116. @Test
    117. public void Test4(){
    118. Collection coll = new ArrayList();
    119. coll.add(123);
    120. coll.add(456);
    121. coll.add(new Person("Jerry",20));
    122. coll.add(new String());
    123. coll.add(false);
    124. // hashCode():返回当前对象的哈希值
    125. System.out.println(coll.hashCode());
    126. // toArray():集合 ---> 数组
    127. Object[] array = coll.toArray();
    128. for(int i = 0;i < array.length;i++){
    129. System.out.println(array[i]);//
    130. }
    131. // 拓展:数组 ---> 集合:调用Arrays类的静态方法asList()
    132. List list = Arrays.asList(new String[]{"AA", "BB", "CC"});
    133. System.out.println(list);
    134. }
    135. }
    1. package com.jiayifeng.java;
    2. import java.util.Objects;
    3. /**
    4. * author 爱编程的小贾
    5. * create 2023-09-19 17:34
    6. */
    7. public class Person {
    8. private String name;
    9. private int age;
    10. public Person(){
    11. }
    12. public Person(String name,int age){
    13. this.name = name;
    14. this.age = age;
    15. }
    16. public String getName() {
    17. return name;
    18. }
    19. public void setName(String name) {
    20. this.name = name;
    21. }
    22. public int getAge() {
    23. return age;
    24. }
    25. public void setAge(int age) {
    26. this.age = age;
    27. }
    28. @Override
    29. public String toString() {
    30. return "Person{" +
    31. "name='" + name + '\'' +
    32. ", age=" + age +
    33. '}';
    34. }
    35. @Override
    36. public boolean equals(Object o) {
    37. System.out.println("Person equals()....");
    38. if (this == o) return true;
    39. if (o == null || getClass() != o.getClass()) return false;
    40. Person person = (Person) o;
    41. return age == person.age && Objects.equals(name, person.name);
    42. }
    43. // @Override
    44. // public int hashCode() {
    45. // return Objects.hash(name, age);
    46. // }
    47. }

    11.3:Iterator迭代器接口


    1. package com.jiayifeng.java;
    2. import org.junit.Test;
    3. import java.util.ArrayList;
    4. import java.util.Collection;
    5. import java.util.Iterator;
    6. /**
    7. * author 爱编程的小贾
    8. * create 2023-09-21 14:42
    9. *
    10. * 一:集合元素的遍历操作,使用迭代器Iterator接口
    11. * 1.定义:提供一种方法访问一个容器(container)对象中的各个元素,而又不暴露该对象
    12. * 的内部细节
    13. * 2.内部的方法:hasNext()和next()
    14. * 3.集合对象每次调用Iterator()方法前都会得到一个全新的迭代器对象,默认游标都在
    15. * 集合的第一个元素之前
    16. * 4.内部定义了remove(),可以在遍历的时候,删除集合中的元素。此方法不同于集合直接
    17. * 调用remove()
    18. */
    19. public class IteratorTest {
    20. @Test
    21. public void Test1(){
    22. Collection coll = new ArrayList();
    23. coll.add(123);
    24. coll.add(456);
    25. coll.add(new Person("Jerry",20));
    26. coll.add(new String("Tom"));
    27. coll.add(false);
    28. Iterator iterator = coll.iterator();
    29. // 方式一:
    30. System.out.println(iterator.next());//123
    31. // 方式二:不推荐
    32. // for(int i = 0;i < coll.size();i++){
    33. // System.out.println(iterator.next());
    34. // }
    35. // 方式三:推荐
    36. while(iterator.hasNext()){//hasNext():判断是否还有下一个元素
    37. System.out.println(iterator.next());//next():①指针下移②将下移以后集合位置上的元素返回
    38. }
    39. }
    40. @Test
    41. public void test2(){
    42. Collection coll = new ArrayList();
    43. coll.add(123);
    44. coll.add(456);
    45. coll.add(new Person("Jerry",20));
    46. coll.add(new String("Tom"));
    47. coll.add(false);
    48. // 错误方式一:
    49. Iterator iterator = coll.iterator();
    50. while((iterator.next()) != null){
    51. System.out.println(iterator.next());
    52. // java.util.NoSuchElementException
    53. // 错误方式二:
    54. while(coll.iterator().hasNext()){
    55. System.out.println(coll.iterator().next());
    56. }
    57. }
    58. }
    59. // 测试Iterator中的remove()
    60. // 如果还未调用next()或在上一次调用next方法以后已经调用了remove方法,
    61. // 再次调用remove都会报IllegalStateException
    62. @Test
    63. public void test3(){
    64. Collection coll = new ArrayList();
    65. coll.add(123);
    66. coll.add(456);
    67. coll.add(new Person("Jerry",20));
    68. coll.add(new String("Tom"));
    69. coll.add(false);
    70. // 删除集合中"Tom"
    71. Iterator iterator = coll.iterator();
    72. while(iterator.hasNext()){
    73. Object obj = iterator.next();
    74. if("Tom".equals(obj)){
    75. iterator.remove();
    76. }
    77. }
    78. iterator = coll.iterator();
    79. while (iterator.hasNext()) {
    80. System.out.println(iterator.next());
    81. }
    82. }
    83. }

    11.4:Collection子接口一:List


    1. package com.jiayifeng.java.java1;
    2. import com.jiayifeng.java.Person;
    3. import org.junit.Test;
    4. import java.util.ArrayList;
    5. import java.util.Arrays;
    6. import java.util.Iterator;
    7. import java.util.List;
    8. /**
    9. * author 爱编程的小贾
    10. * create 2023-09-21 16:48
    11. *
    12. * 一:List框架结构
    13. * 1.|----Collection接口:单列集合,用来存储一个一个的对象
    14. * |----List接口:存储有序的、可重复的数据 ->"动态"数组,替换原有
    15. * 的数组
    16. * |----ArrayList:作为List接口的主要实现类;线程不安全的,
    17. * 效率高;底层使用Object[] elementData存储
    18. * |----LinkedList:对于频繁的插入、删除操作,使用此类效率比
    19. * ArrayList高;底层使用双向循环链表存储
    20. * |----Vector:作为List接口的古老实现类;线程安全的,效率低;
    21. * 底层使用Object[] elementData存储
    22. *
    23. * 2.面试题:ArrayList、LinkedList、Vector三者的异同?
    24. * ①同:三个类都是实现List接口,存储数据的特点相同:存储有序的、可重复的数据
    25. * ②不同:见上
    26. *
    27. * 3.ArrayList的源码分析:
    28. * ①jdk 7的情况下
    29. * ArrayList List = new ArrayList();//底层创建了长度是10的Object[]数组elementData
    30. * list.add(123);//elementData[0] = new Integer(123);
    31. * ...
    32. * list.add(11);//如果此次的添加导致底层elementData数组容量不够,则扩容
    33. * 默认情况下,扩容为原来的1.5倍,同时需要将原有数组中的数据复制到新的数组中
    34. *
    35. * 结论:建议开发中使用带参的构造器:ArrayList list = new ArrayList(int capacity)
    36. * ②jdk 8的情况下的变化
    37. * ArrayList List = new ArrayList();//底层Object[] elementData初始化为{},并没有创建长度为10的数组
    38. * list.add(123)//第一次调用add()时,底层才创建了长度为10的数组,并将数据123添加到elementData[0]
    39. * ...
    40. * 后续的添加与扩容操作与jdk 7.0无异
    41. * ③jdk 7中的ArrayList的对象的创建类类似于单例的饿汉式,而jdk 8中的ArrayList的对象的创建
    42. * 类似于单例的懒汉式,延迟了数组的创建,节省内存
    43. *
    44. * 4.LinkedList的源码分析:
    45. * LinkedList list = new LinkedList();//内部声明了Node类型的first和last属性,默认值为null
    46. * list.add(123);//将123封装到Node中,创建了Node对象
    47. *
    48. * 5.Vector的源码的分析:
    49. * jdk 7和jdk 8中通过Vector()构造器创建对象时,底层都创建了长度为10的数组
    50. * 在扩容方面,默认扩容为原来数组长度的2倍
    51. *
    52. * 6.List接口中的常用方法
    53. * 增:add(Object obj)
    54. * 删:remove(int index) / remove(Object obj)
    55. * 改:set(int index,Object ele)
    56. * 查:get(int index)
    57. * 插:add(int index,Object ele)
    58. * 长度:size()
    59. * 遍历:①Iterator迭代器方式
    60. * ②增强for循环
    61. * ③普通的循环
    62. */
    63. public class ListTest {
    64. @Test
    65. public void test2(){
    66. ArrayList list = new ArrayList();
    67. list.add(123);
    68. list.add(456);
    69. list.add("AA");
    70. // 方式一:Iterator迭代器方式
    71. Iterator iterator = list.iterator();
    72. while(iterator.hasNext()){
    73. System.out.println(iterator.next());
    74. }
    75. System.out.println("******************");
    76. // 方式二:增强for循环
    77. for(Object obj : list){
    78. System.out.println(obj);
    79. }
    80. System.out.println("******************");
    81. // 方式三:普通for循环
    82. for(int i = 0;i < list.size();i++){
    83. System.out.println(list.get(i));
    84. }
    85. }
    86. @Test
    87. public void test1(){
    88. ArrayList list = new ArrayList();
    89. list.add(123);
    90. list.add(456);
    91. list.add("AA");
    92. list.add(new Person("Tom",12));
    93. list.add(456);
    94. System.out.println(list);//[123, 456, AA, Person{name='Tom', age=12}, 456]
    95. // add(int index,Object ele):在index位置插入ele元素
    96. list.add(1,"BB");
    97. System.out.println(list);//[123, BB, 456, AA, Person{name='Tom', age=12}, 456]
    98. // boolean addAll(int index,Collection eles):从index位置开始将eles中的所有元素添加进来
    99. List list1 = Arrays.asList(1,2,3);
    100. list.addAll(list1);
    101. System.out.println(list);//[123, BB, 456, AA, Person{name='Tom', age=12}, 456, 1, 2, 3]
    102. System.out.println(list.size());//9
    103. // Object get(int index):获取指定index位置的元素
    104. System.out.println(list.get(0));//123
    105. // int indexOf(Object obj):返回obj在集合中首次出现的位置;如果不存在,返回-1
    106. System.out.println(list.indexOf(456));//2
    107. // int lastIndexOf(Object obj):返回obj在当前集合中最后一次出现的位置;如果不存在,返回-1
    108. System.out.println(list.lastIndexOf(456));//5
    109. // Object remove(int index):移除指定index位置的元素,并返回此元素
    110. Object obj = list.remove(0);
    111. System.out.println(obj);//123
    112. System.out.println(list);//[BB, 456, AA, Person{name='Tom', age=12}, 456, 1, 2, 3]
    113. // Object set(int index,Object ele):设置指定index位置的元素为ele
    114. list.set(1,"CC");
    115. System.out.println(list);
    116. // List subList(int fromIndex,int toIndex):返回从fromIndex到toIndex位置的左闭右开子集和
    117. System.out.println(list.subList(2,4));//[AA, Person{name='Tom', age=12}]
    118. }
    119. }

    11.5:Collection子接口二:Set


    1. package com.jiayifeng.java.java1;
    2. import org.junit.Test;
    3. import java.util.HashSet;
    4. import java.util.Iterator;
    5. import java.util.LinkedHashSet;
    6. import java.util.Set;
    7. /**
    8. * author 爱编程的小贾
    9. * create 2023-09-21 21:46
    10. *
    11. * 一:Set接口的框架
    12. * 1.|----Collection接口:单列集合,用来存储一个一个的对象
    13. * |----Set接口:存储无序的、不可重复的数据 ->高中讲的“集合”
    14. * |----HashSet:作为Set接口的主要实现类;线程不安全的;
    15. * 可以存储null值
    16. * |----LinkedHashSet:作为HashSet的子类;遍历其
    17. * 内部数据时,可以按照添加的顺序遍历
    18. * |----TreeSet:可以按照添加对象的指定属性,进行排序
    19. *
    20. * 2.Set接口中没有额外定义新的方法,使用的都是Collection中声明过的方法
    21. *
    22. * 3.要求:向Set中添加的数据,其所在的类一定要重写hashCode()和equals()
    23. * 要求:重写的hashCode()和equals()尽可能保持一致性:相等的对象必须具有相
    24. * 等的散列码
    25. * 重写两个方法的小技巧:对象中用作equals()方法比较的Field,都应该用来计算
    26. * hashCode值
    27. */
    28. public class SetTest {
    29. /*
    30. 一:Set:存储无序的、不可重复的数据
    31. 1.无序性:不等于随机性
    32. 存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数组的哈希值决定的
    33. 2.不可重复性:保证添加的元素按照equals()判断时,不能返回true。即:相同的元素
    34. 只能添加一个
    35. 二:添加元素的过程:以HashSet为例
    36. 我们向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值,此哈希值
    37. 接着通过某种算法计算出在HashSet底层数组中的存放位置(即为:索引位置),判断数组此位置上是否已经有元素:
    38. 如果此位置上没有其他元素,则元素a添加成功 --->情况1
    39. 如果此位置上有其他元素b(或以链表形式存在的多个元素),则比较元素a与元素b的hash值:
    40. 如果hash值不相同,则元素a添加成功 --->情况2
    41. 如果hash值相同,进而需要调用元素a所在类的equals()方法:
    42. equals()返回true,元素a添加失败
    43. equals()返回false,则元素a添加成功 --->情况3
    44. 对于添加成功的情况2和情况3而言,元素a与已经存在指定索引位置上数据以链表的方式存储
    45. jdk 7:元素a放到数组中,指向原来的元素
    46. jdk 8:原来的元素在数组中,指向元素a
    47. 总结:七上八下
    48. HashSet底层:数组 + 链表的结构
    49. */
    50. @Test
    51. public void test1() {
    52. Set set = new HashSet();
    53. set.add(456);
    54. set.add(123);
    55. set.add("AA");
    56. set.add("CC");
    57. set.add(new User("Tom", 12));
    58. set.add(new User("Tom", 12));
    59. set.add(129);
    60. Iterator iterator = set.iterator();
    61. while (iterator.hasNext()) {
    62. System.out.println(iterator.next());
    63. }
    64. }
    65. // LinkedHashSet的使用
    66. // LinkedHashSet作为HashSet的子类,在添加数据的同时,每个数据还维护了两个引用
    67. // ,记录此数据前一个数据和后一个数据
    68. // 优点:对于频繁的遍历操作,LinkedHashSet效率高于HashSet
    69. @Test
    70. public void test2() {
    71. Set set = new LinkedHashSet();
    72. set.add(456);
    73. set.add(123);
    74. set.add("AA");
    75. set.add("CC");
    76. set.add(new User("Tom", 12));
    77. set.add(new User("Tom", 12));
    78. set.add(129);
    79. Iterator iterator = set.iterator();
    80. while (iterator.hasNext()) {
    81. System.out.println(iterator.next());
    82. }
    83. }
    84. }
    1. package com.jiayifeng.java.java1;
    2. import org.junit.Test;
    3. import java.util.Comparator;
    4. import java.util.Iterator;
    5. import java.util.TreeSet;
    6. /**
    7. * author 爱编程的小贾
    8. * create 2023-09-23 11:27
    9. *
    10. * 一:TreeSetTest的使用
    11. */
    12. public class TreeSetTest {
    13. /*
    14. 1.向TreeSet中添加的数据,要求是相同类的对象
    15. 2.两种排序方式:自然排序(实现Comparable接口)和定制排序(Comparator)
    16. 3.自然排序中,比较两个对象是否相同的标准为:comparaTo()返回0,不再是equals()
    17. 4.定制排序中,比较两个对象是否相同的标准为:compara()返回0,不再是equals()
    18. */
    19. @Test
    20. public void test1(){
    21. TreeSet set = new TreeSet();
    22. // 举例一:
    23. // set.add(34);
    24. // set.add(-34);
    25. // set.add(43);
    26. // set.add(11);
    27. // set.add(8);
    28. // 举例二:
    29. set.add(new User("Tom",12));
    30. set.add(new User("Jerry",32));
    31. set.add(new User("Jim",2));
    32. set.add(new User("Mike",65));
    33. set.add(new User("Jack",33));
    34. set.add(new User("Jack",56));
    35. Iterator iterator = set.iterator();
    36. while (iterator.hasNext()) {
    37. System.out.println(iterator.next());
    38. }
    39. }
    40. @Test
    41. public void test2() {
    42. Comparator com = new Comparator() {
    43. // 按照年龄从小到大排序
    44. @Override
    45. public int compare(Object o1, Object o2) {
    46. if (o1 instanceof User && o2 instanceof User) {
    47. User u1 = (User)o1;
    48. User u2 = (User)o2;
    49. return Integer.compare(u1.getAge(),u2.getAge());
    50. }else{
    51. throw new RuntimeException("输入的数据类型不匹配");
    52. }
    53. }
    54. };
    55. TreeSet set = new TreeSet(com);
    56. set.add(new User("Tom", 12));
    57. set.add(new User("Jerry", 32));
    58. set.add(new User("Jim", 2));
    59. set.add(new User("Mike", 65));
    60. set.add(new User("Jack", 33));
    61. set.add(new User("Jack", 56));
    62. Iterator iterator = set.iterator();
    63. while (iterator.hasNext()) {
    64. System.out.println(iterator.next());
    65. }
    66. }
    67. }
    1. package com.jiayifeng.java1;
    2. import java.util.Objects;
    3. /**
    4. * author 爱编程的小贾
    5. * create 2023-09-21 22:02
    6. */
    7. public class User implements Comparable{
    8. private String name;
    9. private int age;
    10. public User() {
    11. }
    12. public User(String name, int age) {
    13. this.name = name;
    14. this.age = age;
    15. }
    16. public String getName() {
    17. return name;
    18. }
    19. public void setName(String name) {
    20. this.name = name;
    21. }
    22. public int getAge() {
    23. return age;
    24. }
    25. public void setAge(int age) {
    26. this.age = age;
    27. }
    28. @Override
    29. public String toString() {
    30. return "User{" +
    31. "name='" + name + '\'' +
    32. ", age=" + age +
    33. '}';
    34. }
    35. @Override
    36. public boolean equals(Object o) {
    37. if (this == o) return true;
    38. if (o == null || getClass() != o.getClass()) return false;
    39. User user = (User) o;
    40. return age == user.age && Objects.equals(name, user.name);
    41. }
    42. @Override
    43. public int hashCode() {
    44. return Objects.hash(name, age);
    45. }
    46. // 按照姓名从大到小排列,年龄从小到大排列
    47. @Override
    48. public int compareTo(Object o) {
    49. if (o instanceof User) {
    50. User user = (User) o;
    51. int compare = -this.name.compareTo(user.name);
    52. if (compare != 0) {
    53. return compare;
    54. } else {
    55. return Integer.compare(this.age, user.age);
    56. }
    57. } else {
    58. throw new RuntimeException("输入的类型不匹配");
    59. }
    60. }
    61. }

    11.6:Map接口


    1. package com.jiayifeng.java.java2;
    2. import org.junit.Test;
    3. import java.util.*;
    4. /**
    5. * author 爱编程的小贾
    6. * create 2023-09-27 8:19
    7. *
    8. * 一:Map实现类的结构
    9. * |----Map:双列数据,存储key-value对的数据 ---类似于高中的函数:y=f(x)
    10. * |----HashMap:作为Map的主要实现类;线程不安全的,效率高;存储null的key和value
    11. * |LinkedHashMap:保证在遍历map元素时,可以按照添加的顺序实现遍历
    12. * 原因:在原有的HashMap底层结构的基础上,添加了一对指针,指向前一
    13. * 个和后一个元素
    14. * 对于频繁的遍历操作,使用此类的执行效率高
    15. * |----TreeMap:保证按照添加的顺序key-value对进行排序,实现排序遍历;此时
    16. * 考虑key的自然排序和定制排序
    17. * 底层使用红黑树
    18. * |----Hashtable:作为古老的实现类;线程安全的,效率低;不能存储null的key和value
    19. * |----properties:常用来处理配置文件。key和value都是String类型
    20. *
    21. * HashMap的底层:数组+列表(jdk 7及以前)
    22. * 数组+列表+红黑树(jdk 8)
    23. *
    24. * 二:面试题:
    25. * ①HashMap的底层实现原理?
    26. * ②HashMap和Hashtable的异同?
    27. * ③CurrentHashMap和Hashtable的异同?
    28. *
    29. * 三:Map结构的理解
    30. * Map中的key:无序的、不可重复的,使用Set存储所有的key --->key所在的类要
    31. * 重写equals()和hashCode(),以HashMap为例
    32. * Map中的value:无序的、可重复的,使用Collection存储所有的value --->
    33. * value所在的类要重写equals()
    34. * 一个键值对:key-value构成了一个Entry对象
    35. * Map中的entry:无序的、不可重复的,使用Set存储所有的entry
    36. *
    37. * 四:HashMap的底层实现原理?(以jdk 7为例说明)
    38. * HashMap map = new HashMap();
    39. * 在实例化以后,底层创建了长度是16的一维数组Entry[] table
    40. * ...可能已经执行过多次put...
    41. * map.put(key1,value1):
    42. * 首先,调用key1所在类的HashCode()计算key1的哈希值,此哈希值经过某种算法
    43. * 以后,得到在Entry数组中的存放位置
    44. * 如果此位置上的数据为空,此时的key1-value1添加成功 ----情况一
    45. * 如果此位置上的数据不为空(意味着此位置上存在一个或多个数据(以链表形式存在)),
    46. * 比较key1和已经存在的一个或多个数据的哈希值:
    47. * 如果key1的哈希值与已经存在的数据的哈希值都不相同,此时的key1-value1
    48. * 添加成功 ----情况二
    49. * 如果key1的哈希值与已经存在的某一个数据(key2-value2)的哈希值相同,
    50. * 继续比较:调用key1所在类的equals(key2)
    51. * 如果equals()返回false:此时key1-value1添加成功 ----情况三
    52. * 如果equals()返回true:使用value1替换value2
    53. *
    54. * 补充:关于情况二和情况三:此时key1-value1和原来的数据以链表的方式存储
    55. *
    56. * 在不断地添加过程中,会涉及扩容问题,默认的扩容方式:扩容为原来容量的2倍,
    57. * 并将原有的数据复制过来
    58. *
    59. * jdk 8相较于jdk 7在底层实现方面的不同:
    60. * ①new HashMap():底层没有创建一个长度为16的数组
    61. * ②jdk 8底层的数组是:Node[],而非Entry[]
    62. * ③首次使用put()方法时,底层创建长度为16的数组
    63. * ④jdk 7底层结构只有:数组+链表
    64. * jdk 8底层结构:数组+链表+红黑树
    65. * 当数组的某一个索引位置上的元素以链表形式存在的数据个数 > 8 且当前数组的长度 > 64时,
    66. * 此时此索引位置上的所有数据改为使用红黑树存储
    67. *
    68. * 五:LinkedHashMap的底层实现原理
    69. * 源码中:
    70. * static class Entry extends HashMap.Node {
    71. * Entry before, after;//可以记录元素添加的先后顺序
    72. * Entry(int hash, K key, V value, Node next) {
    73. * super(hash, key, value, next);
    74. * }
    75. * }
    76. *
    77. * 六:Map中的常用方法
    78. * 添加:put()
    79. * 删除:remove()
    80. * 修改:put()
    81. * 查询:get()
    82. * 长度:size()
    83. * 遍历:keySet()/values()/entrySet()
    84. *
    85. */
    86. public class MapTest {
    87. @Test
    88. public void test1(){
    89. Map map = new HashMap();
    90. // map = new LinkedHashMap();
    91. // map.put(null,null);
    92. // 添加
    93. map.put("AA",123);
    94. map.put(45,123);
    95. map.put("BB",56);
    96. // 修改
    97. map.put("AA",87);
    98. System.out.println(map);//{AA=87, BB=56, 45=123}
    99. Map map1 = new HashMap();
    100. map1.put("CC",123);
    101. map1.put("DD",123);
    102. map.putAll(map1);
    103. System.out.println(map);//{AA=87, BB=56, CC=123, DD=123, 45=123}
    104. // remove(Object key)
    105. Object value = map.remove("CC");
    106. System.out.println(value);//123
    107. System.out.println(map);//{AA=87, BB=56, DD=123, 45=123}
    108. // clear()
    109. map.clear();//与map=null操作不同
    110. System.out.println(map);//{}
    111. System.out.println(map.size());//0
    112. }
    113. @Test
    114. public void test2(){
    115. // 元素查询操作
    116. Map map = new HashMap();
    117. map.put("AA",123);
    118. map.put(45,123);
    119. map.put("BB",56);
    120. // Object get(Object key):获取指定key对应的value
    121. System.out.println(map.get(45));//123
    122. // boolean containKey(Object key):是否包含指定的key
    123. boolean isExist = map.containsKey("BB");
    124. System.out.println(isExist);//true
    125. // boolean containValue(Object value):是否包含指定的value
    126. boolean isExist1 = map.containsValue(123);
    127. System.out.println(isExist1);//true
    128. // int size():返回map中key-value对的个数
    129. // boolean isEmpty():判断当前map是否为空
    130. map.clear();
    131. System.out.println(map.isEmpty());//true
    132. // boolean equals(Object obj):判断当前map和参数对象obj是否相等
    133. }
    134. @Test
    135. public void test3(){
    136. // 元视图操作的方法
    137. Map map = new HashMap();
    138. map.put("AA",123);
    139. map.put(45,1234);
    140. map.put("BB",56);
    141. // Set keySet():返回所有key构成的Set集合
    142. Set set = map.keySet();
    143. Iterator iterator = set.iterator();
    144. while(iterator.hasNext()){
    145. System.out.print(iterator.next() + " ");//AA BB 45
    146. }
    147. System.out.println();
    148. // Collection values():返回所有value构成的Collection集合
    149. Collection values = map.values();
    150. // Iterator iterator1 = values.iterator();
    151. // while (iterator1.hasNext()) {
    152. // System.out.print(iterator1.next() + " ");
    153. // }
    154. for(Object obj : values){
    155. System.out.print(obj + " ");//123 56 1234
    156. }
    157. // Set entrySet():返回所有key-value对构成的Set集合
    158. // 方式一:
    159. Set entrySet = map.entrySet();
    160. Iterator iterator2 = entrySet.iterator();
    161. while (iterator2.hasNext()) {
    162. Object obj = iterator2.next();
    163. // entrySet集合中的元素都是entry
    164. Map.Entry entry = (Map.Entry)obj;
    165. System.out.println(entry.getKey() + "--->" + entry.getValue());
    166. /*
    167. AA--->123
    168. BB--->56
    169. 45--->1234
    170. */
    171. // 方式二:
    172. Set keySet = map.keySet();
    173. Iterator iterator3 = keySet.iterator();
    174. while(iterator3.hasNext()){
    175. Object key = iterator3.next();
    176. Object value = map.get(key);
    177. System.out.println(key + "---->" + value);
    178. }
    179. }
    180. }
    181. }
    1. package com.jiayifeng.java2;
    2. import org.junit.Test;
    3. import java.util.*;
    4. /**
    5. * author 爱编程的小贾
    6. * create 2023-10-08 16:51
    7. */
    8. public class TreeMapTest {
    9. // 向TreeMap中添加key-value,要求必须是由同一个类创建的对象
    10. // 因为要按照key进行排序:自然排序、定制排序
    11. // 自然排序
    12. @Test
    13. public void Test1() {
    14. TreeMap map = new TreeMap();
    15. User u1 = new User("Tom", 23);
    16. User u2 = new User("Jack", 25);
    17. User u3 = new User("Jerry", 33);
    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 iterator = entrySet.iterator();
    25. while (iterator.hasNext()) {
    26. Object obj = iterator.next();
    27. // entrySet集合中的元素都是entry
    28. Map.Entry entry = (Map.Entry) obj;
    29. System.out.println(entry.getKey() + "--->" + entry.getValue());
    30. }
    31. }
    32. // 定制排序
    33. @Test
    34. public void test2(){
    35. TreeMap map = new TreeMap(new Comparator() {
    36. @Override
    37. public int compare(Object o1, Object o2) {
    38. if (o1 instanceof User && o2 instanceof User) {
    39. User u1 = (User)o1;
    40. User u2 = (User)o2;
    41. return Integer.compare(u1.getAge(),u2.getAge());
    42. }
    43. throw new RuntimeException("输入的类型不匹配!");
    44. }
    45. });
    46. User u1 = new User("Tom", 23);
    47. User u2 = new User("Jack", 25);
    48. User u3 = new User("Jerry", 33);
    49. User u4 = new User("Rose", 18);
    50. map.put(u1, 98);
    51. map.put(u2, 89);
    52. map.put(u3, 76);
    53. map.put(u4, 100);
    54. Set entrySet = map.entrySet();
    55. Iterator iterator = entrySet.iterator();
    56. while (iterator.hasNext()) {
    57. Object obj = iterator.next();
    58. // entrySet集合中的元素都是entry
    59. Map.Entry entry = (Map.Entry) obj;
    60. System.out.println(entry.getKey() + "--->" + entry.getValue());
    61. }
    62. }
    63. }
    1. package com.jiayifeng.java2;
    2. import java.io.FileInputStream;
    3. import java.io.FileNotFoundException;
    4. import java.io.IOException;
    5. import java.util.Properties;
    6. /**
    7. * author 爱编程的小贾
    8. * create 2023-10-08 17:12
    9. */
    10. public class PropertiesTest {
    11. // properties:常用来处理配置文件。key和value都是String类型
    12. public static void main(String[] args) throws IOException {
    13. Properties pros = new Properties();
    14. FileInputStream fileInputStream = new FileInputStream("jdbc.properties");
    15. pros.load(fileInputStream);//加载流对应的文件
    16. String name = pros.getProperty("name");
    17. String passwd = pros.getProperty("passwd");
    18. System.out.println("name =" + name + "passwd =" + passwd);
    19. }
    20. }

    11.7:Collections工具类


    1. package com.jiayifeng1.java;
    2. import org.junit.Test;
    3. import java.util.*;
    4. /**
    5. * author 爱编程的小贾
    6. * create 2023-10-08 17:28
    7. *
    8. * Collections:操作Collection、Map的工具类
    9. *
    10. * 面试题:Collection和Collections的区别?
    11. *
    12. */
    13. public class CollectionsTest {
    14. @Test
    15. public void test1(){
    16. List list = new ArrayList();
    17. list.add(123);
    18. list.add(43);
    19. list.add(765);
    20. list.add(765);
    21. list.add(765);
    22. list.add(-97);
    23. list.add(0);
    24. System.out.println(list);
    25. // 反转
    26. Collections.reverse(list);
    27. System.out.println(list);
    28. // 随机排序
    29. Collections.shuffle(list);
    30. System.out.println(list);
    31. // 升序排序
    32. Collections.sort(list);
    33. System.out.println(list);
    34. // 交换
    35. Collections.swap(list,1,2);
    36. System.out.println(list);
    37. // 统计出现的次数
    38. int frequency = Collections.frequency(list, 765);
    39. System.out.println(list);
    40. System.out.println(frequency);
    41. }
    42. @Test
    43. public void test2(){
    44. List list = new ArrayList();
    45. list.add(123);
    46. list.add(43);
    47. list.add(765);
    48. list.add(-97);
    49. list.add(0);
    50. System.out.println(list);
    51. // 将list中的内容复制到dest中
    52. List dest = Arrays.asList(new Object[list.size()]);
    53. System.out.println(dest.size());
    54. Collections.copy(dest,list);
    55. System.out.println(dest);
    56. /*
    57. [123, 43, 765, -97, 0]
    58. 5
    59. [123, 43, 765, -97, 0]
    60. */
    61. }
    62. }

    11.8:增强for循环


    1. package com.jiayifeng.java;
    2. import org.junit.Test;
    3. import java.util.ArrayList;
    4. import java.util.Collection;
    5. /**
    6. * author 爱编程的小贾
    7. * create 2023-09-21 16:32
    8. *
    9. * 一:jdk 5.0新增了foreach循环,用于遍历数组、集合
    10. */
    11. public class ForTest {
    12. @Test
    13. public void test1(){
    14. Collection coll = new ArrayList();
    15. coll.add(123);
    16. coll.add(456);
    17. coll.add(new Person("Jerry",20));
    18. coll.add(new String("Tom"));
    19. coll.add(false);
    20. // for(集合元素的类型 局部变量 : 集合对象)
    21. // 内部仍然调用了迭代器
    22. for(Object obj : coll){
    23. System.out.println(obj);
    24. }
    25. }
    26. @Test
    27. public void test2(){
    28. // 遍历数组
    29. int[] arr = new int[]{1,2,3,4,5,6};
    30. for(int i : arr){
    31. System.out.println(i);
    32. }
    33. }
    34. @Test
    35. public void test3(){
    36. String[] arr = new String[]{"MM","MM","MM"};
    37. // 方式一:普通for赋值
    38. // for(int i = 0;i < arr.length;i++){
    39. // arr[i] = "GG";
    40. // }
    41. // 方式二:增强for循环
    42. for(String s : arr){
    43. s = "GG";
    44. }
    45. for(int i = 0;i < arr.length;i++){
    46. System.out.println(arr[i]);
    47. }
    48. }
    49. }
  • 相关阅读:
    王杰qtday4
    JavaScript中的运算符
    【滤波跟踪】基于粒子群算法优化粒子滤波实现目标滤波跟踪优化问题附matlab代码
    vite+vue3+ts中使用require.context | 报错require is not defined | 获取文件夹中的文件名
    一套次世代建模的流程是怎样的?
    程序员的数学课16 二分法:如何利用指数爆炸优化程序?
    习题:选择结构(二)
    【Python高级语法】——迭代器 (Iterator)
    CentOs7 彻底卸载清除docker
    知识图谱(5)知识表示
  • 原文地址:https://blog.csdn.net/weixin_63925896/article/details/133031594