当前位置: 首页 > news >正文

第十一部分 Java 数据结构及集合

第十一部分 Java 数据结构及集合

11.1 Java 数据结构

Java 提供了丰富的数据结构来处理和组织数据。

Java 的 java.util 包中提供了许多这些数据结构的实现,可以根据需要选择合适的类。

以下是一些常见的 Java 数据结构:

11.1.1 数组(Arrays)

数组(Arrays)是一种基本的数据结构,可以存储固定大小的相同类型的元素。

int[] array = new int[5];
  • 特点: 固定大小,存储相同类型的元素。
  • 优点: 随机访问元素效率高。
  • 缺点: 大小固定,插入和删除元素相对较慢。
11.1.2 列表(Lists)

Java 提供了多种列表实现,如 ArrayList 和 LinkedList。

List<String> arrayList = new ArrayList<>();
List<Integer> linkedList = new LinkedList<>();

ArrayList:

  • 特点: 动态数组,可变大小。
  • 优点: 高效的随机访问和快速尾部插入。
  • 缺点: 中间插入和删除相对较慢。

LinkedList:

  • 特点: 双向链表,元素之间通过指针连接。
  • 优点: 插入和删除元素高效,迭代器性能好。
  • 缺点: 随机访问相对较慢。
11.1.3 集合(Sets)

集合(Sets)用于存储不重复的元素,常见的实现有 HashSet 和 TreeSet。

Set<String> hashSet = new HashSet<>();
Set<Integer> treeSet = new TreeSet<>();

HashSet:

  • 特点: 无序集合,基于HashMap实现。
  • 优点: 高效的查找和插入操作。
  • 缺点: 不保证顺序。

TreeSet:

  • **特点:**TreeSet 是有序集合,底层基于红黑树实现,不允许重复元素。
  • 优点: 提供自动排序功能,适用于需要按顺序存储元素的场景。
  • 缺点: 性能相对较差,不允许插入 null 元素。
11.1.4 映射(Maps)

映射(Maps)用于存储键值对,常见的实现有 HashMap 和 TreeMap。

Map<String, Integer> hashMap = new HashMap<>();
Map<String, Integer> treeMap = new TreeMap<>();

HashMap:

  • 特点: 基于哈希表实现的键值对存储结构。
  • 优点: 高效的查找、插入和删除操作。
  • 缺点: 无序,不保证顺序。

TreeMap:

  • 特点: 基于红黑树实现的有序键值对存储结构。
  • 优点: 有序,支持按照键的顺序遍历。
  • 缺点: 插入和删除相对较慢。
11.1.5 栈(Stack)

栈(Stack)是一种线性数据结构,它按照后进先出(Last In, First Out,LIFO)的原则管理元素。在栈中,新元素被添加到栈的顶部,而只能从栈的顶部移除元素。这就意味着最后添加的元素是第一个被移除的。

Stack<Integer> stack = new Stack<>();

Stack 类:

  • 特点: 代表一个栈,通常按照后进先出(LIFO)的顺序操作元素。
11.1.6 队列(Queue)

队列(Queue)遵循先进先出(FIFO)原则,常见的实现有 LinkedList 和 PriorityQueue。

Queue<String> queue = new LinkedList<>();

Queue 接口:

  • 特点: 代表一个队列,通常按照先进先出(FIFO)的顺序操作元素。
  • 实现类: LinkedList, PriorityQueue, ArrayDeque。
11.1.7 堆(Heap)

堆(Heap)优先队列的基础,可以实现最大堆和最小堆。

PriorityQueue<Integer> minHeap = new PriorityQueue<>();
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());
11.1.8 树(Trees)

Java 提供了 TreeNode 类型,可以用于构建二叉树等数据结构。

class TreeNode {int val;TreeNode left;TreeNode right;TreeNode(int x) { val = x; }
}
11.1.9 图(Graphs)

图的表示通常需要自定义数据结构或使用图库,Java 没有内建的图类。

以上介绍的只是 Java 中一些常见的数据结构,实际上还有很多其他的数据结构和算法可以根据具体问题选择使用。

11.2 泛型

11.2.1 泛型概述
  • 泛型的介绍

    泛型是JDK5中引入的特性,它提供了编译时类型安全检测机制。

    需要明确的是,Java中的泛型是伪泛型。

  • 泛型的意义

    作为一种规范,约束存入的数据类型。

  • 泛型的好处

    1. 把运行时期的问题提前到了编译期间
    2. 避免了强制类型转换
  • 泛型的细节

    • 泛型中不能写基本数据类型
    • 指定泛型的具体类型后,传递数据后,可以传入该类类型或者其子类型
    • 如果不写泛型,类型默认是Object
  • 泛型的定义格式

    • <类型>: 指定一种类型的格式.尖括号里面可以任意书写,一般只写一个字母.例如: <E> <T>
    • <类型1,类型2…>: 指定多种类型的格式,多种类型之间用逗号隔开.例如: <E,T> <K,V>
11.2.2 泛型类

定义格式:

修饰符 类名<类型>{}
public class MyArrayList<E> {}
11.2.3 泛型方法

定义格式:

修饰符 <类型> 返回值类型 方法名(类名 变量名){}
public <T> void show(T t) {}

11.3 Collection集合

11.3.1数组和集合的区别
  • 相同点

    都是容器,可以存储多个数据

  • 不同点

    • 数组的长度是不可变的,集合的长度是可变的

    • 数组可以存基本数据类型和引用数据类型

      集合只能存引用数据类型,如果要存基本数据类型,需要存对应的包装类

11.3.2集合类体系结构

11.3.3Collection 集合概述和使用
  • Collection集合概述

    • 是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素
    • JDK 不提供此接口的任何直接实现.它提供更具体的子接口(如Set和List)实现
  • 创建Collection集合的对象

    • 多态的方式
    • 具体的实现类ArrayList
  • Collection集合常用方法

    方法名说明
    boolean add(E e)添加元素
    boolean remove(Object o)从集合中移除指定的元素
    boolean removeIf(Object o)根据条件进行移除
    void clear()清空集合中的元素
    boolean contains(Object o)判断集合中是否存在指定的元素
    boolean isEmpty()判断集合是否为空
    int size()集合的长度,也就是集合中元素的个数
11.3.4Collection集合的遍历
11.3.4.1 迭代器遍历
  • 迭代器介绍

    • 迭代器,集合的专用遍历方式
    • Iterator iterator(): 返回此集合中元素的迭代器,通过集合对象的iterator()方法得到
  • Iterator中的常用方法

    ​ boolean hasNext(): 判断当前位置是否有元素可以被取出
    ​ E next(): 获取当前位置的元素,将迭代器对象移向下一个索引位置

  • Collection集合的遍历

    public class IteratorDemo1 {public static void main(String[] args) {//创建集合对象Collection<String> c = new ArrayList<>();//添加元素c.add("hello");c.add("world");c.add("java");c.add("javaee");//Iterator<E> iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到Iterator<String> it = c.iterator();//用while循环改进元素的判断和获取while (it.hasNext()) {String s = it.next();System.out.println(s);}}
    }
    
  • 迭代器中删除的方法

    ​ void remove(): 删除迭代器对象当前指向的元素

    public class IteratorDemo2 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("a");list.add("b");list.add("b");list.add("c");list.add("d");Iterator<String> it = list.iterator();while(it.hasNext()){String s = it.next();if("b".equals(s)){//指向谁,那么此时就删除谁.it.remove();}}System.out.println(list);}
    }
    
11.3.4.2 增强for
  • 介绍

    • 它是JDK5之后出现的,其内部原理是一个Iterator迭代器
    • 实现Iterable接口的类才可以使用迭代器和增强for
    • 简化数组和Collection集合的遍历
  • 格式

    ​ for(集合/数组中元素的数据类型 变量名 : 集合/数组名) {

    ​ // 已经将当前遍历到的元素封装到变量中了,直接使用变量即可

    ​ }

  • 代码

    public class MyCollectonDemo1 {public static void main(String[] args) {ArrayList<String> list =  new ArrayList<>();list.add("a");list.add("b");list.add("c");list.add("d");list.add("e");list.add("f");//1,数据类型一定是集合或者数组中元素的类型//2,str仅仅是一个变量名而已,在循环的过程中,依次表示集合或者数组中的每一个元素//3,list就是要遍历的集合或者数组for(String str : list){System.out.println(str);}}
    }
    
  • 细节点注意:

1.报错NoSuchElementException

2.迭代器遍历完毕,指针不会复位

3.循环中只能用一次next方法

4.迭代器遍历时,不能用集合的方法进行增加或者删除

public class A04_CollectionDemo4 {public static void main(String[] args) {/*迭代器的细节注意点:1.报错NoSuchElementException2.迭代器遍历完毕,指针不会复位3.循环中只能用一次next方法4.迭代器遍历时,不能用集合的方法进行增加或者删除暂时当做一个结论先行记忆,在今天我们会讲解源码详细的再来分析。如果我实在要删除:那么可以用迭代器提供的remove方法进行删除。如果我要添加,暂时没有办法。(只是暂时)*///1.创建集合并添加元素Collection<String> coll = new ArrayList<>();coll.add("aaa");coll.add("bbb");coll.add("ccc");coll.add("ddd");//2.获取迭代器对象//迭代器就好比是一个箭头,默认指向集合的0索引处Iterator<String> it = coll.iterator();//3.利用循环不断的去获取集合中的每一个元素while(it.hasNext()){//4.next方法的两件事情:获取元素并移动指针String str = it.next();System.out.println(str);}//当上面循环结束之后,迭代器的指针已经指向了最后没有元素的位置//System.out.println(it.next());//NoSuchElementException//迭代器遍历完毕,指针不会复位System.out.println(it.hasNext());//如果我们要继续第二次遍历集合,只能再次获取一个新的迭代器对象Iterator<String> it2 = coll.iterator();while(it2.hasNext()){String str = it2.next();System.out.println(str);}}
}
11.3.4.3 lambda表达式

​ 利用forEach方法,再结合lambda表达式的方式进行遍历

public class A07_CollectionDemo7 {public static void main(String[] args) {/* lambda表达式遍历:default void forEach(Consumer<? super T> action):*///1.创建集合并添加元素Collection<String> coll = new ArrayList<>();coll.add("zhangsan");coll.add("lisi");coll.add("wangwu");//2.利用匿名内部类的形式//底层原理://其实也会自己遍历集合,依次得到每一个元素//把得到的每一个元素,传递给下面的accept方法//s依次表示集合中的每一个数据/* coll.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}});*///lambda表达式coll.forEach(s -> System.out.println(s));}
}

11.4 List集合

11.4.1List集合的概述和特点
  • List集合的概述

    • 有序集合,这里的有序指的是存取顺序
    • 用户可以精确控制列表中每个元素的插入位置,用户可以通过整数索引访问元素,并搜索列表中的元素
    • 与Set集合不同,列表通常允许重复的元素
  • List集合的特点

    • 存取有序
    • 可以重复
    • 有索引
  • List集合子类的特点

    • ArrayList集合

    ​ 底层是数组结构实现,查询快、增删慢

    • LinkedList集合

    ​ 底层是链表结构实现,查询慢、增删快

11.4.2List集合的特有方法
  • 方法介绍

    方法名描述
    void add(int index,E element)在此集合中的指定位置插入指定的元素
    E remove(int index)删除指定索引处的元素,返回被删除的元素
    E set(int index,E element)修改指定索引处的元素,返回被修改的元素
    E get(int index)返回指定索引处的元素
  • 示例代码

    public class MyListDemo {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("aaa");list.add("bbb");list.add("ccc");//method1(list);//method2(list);//method3(list);//method4(list);}private static void method4(List<String> list) {//        E get(int index)		返回指定索引处的元素String s = list.get(0);System.out.println(s);}private static void method3(List<String> list) {//        E set(int index,E element)	修改指定索引处的元素,返回被修改的元素//被替换的那个元素,在集合中就不存在了.String result = list.set(0, "qqq");System.out.println(result);System.out.println(list);}private static void method2(List<String> list) {//        E remove(int index)		删除指定索引处的元素,返回被删除的元素//在List集合中有两个删除的方法//第一个 删除指定的元素,返回值表示当前元素是否删除成功//第二个 删除指定索引的元素,返回值表示实际删除的元素String s = list.remove(0);System.out.println(s);System.out.println(list);}private static void method1(List<String> list) {//        void add(int index,E element)	在此集合中的指定位置插入指定的元素//原来位置上的元素往后挪一个索引.list.add(0,"qqq");System.out.println(list);}
    }
    
11.4.3List集合的五种遍历方式
  1. 迭代器
  2. 列表迭代器
  3. 增强for
  4. Lambda表达式
  5. 普通for循环

代码示例:

//创建集合并添加元素
List<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");//1.迭代器
/*Iterator<String> it = list.iterator();while(it.hasNext()){String str = it.next();System.out.println(str);
}*///2.增强for
//下面的变量s,其实就是一个第三方的变量而已。
//在循环的过程中,依次表示集合中的每一个元素
/* for (String s : list) {System.out.println(s);}*///3.Lambda表达式
//forEach方法的底层其实就是一个循环遍历,依次得到集合中的每一个元素
//并把每一个元素传递给下面的accept方法
//accept方法的形参s,依次表示集合中的每一个元素
//list.forEach(s->System.out.println(s) );//4.普通for循环
//size方法跟get方法还有循环结合的方式,利用索引获取到集合中的每一个元素
/*for (int i = 0; i < list.size(); i++) {//i:依次表示集合中的每一个索引String s = list.get(i);System.out.println(s);}*/// 5.列表迭代器
//获取一个列表迭代器的对象,里面的指针默认也是指向0索引的//额外添加了一个方法:在遍历的过程中,可以添加元素
ListIterator<String> it = list.listIterator();
while(it.hasNext()){String str = it.next();if("bbb".equals(str)){//qqqit.add("qqq");}
}
System.out.println(list);
11.4.4 细节点注意:

List系列集合中的两个删除的方法

1.直接删除元素
2.通过索引进行删除

代码示例:

//List系列集合中的两个删除的方法
//1.直接删除元素
//2.通过索引进行删除//1.创建集合并添加元素
List<Integer> list = new ArrayList<>();list.add(1);
list.add(2);
list.add(3);//2.删除元素
//请问:此时删除的是1这个元素,还是1索引上的元素?
//为什么?
//因为在调用方法的时候,如果方法出现了重载现象
//优先调用,实参跟形参类型一致的那个方法。//list.remove(1);//手动装箱,手动把基本数据类型的1,变成Integer类型
Integer i = Integer.valueOf(1);list.remove(i);System.out.println(list);

11.5 ArrayList

11.5.1 ArrayList类概述
  • 什么是集合

    ​ 提供一种存储空间可变的存储模型,存储的数据容量可以发生改变

  • ArrayList集合的特点

    ​ 长度可以变化,只能存储引用数据类型。

  • 泛型的使用

    ​ 用于约束集合中存储元素的数据类型

11.5.2 ArrayList类常用方法
11.5.2.1 构造方法
方法名说明
public ArrayList()创建一个空的集合对象
11.3.2.2 成员方法
方法名说明
public boolean add(要添加的元素)将指定的元素追加到此集合的末尾
public boolean remove(要删除的元素)删除指定元素,返回值表示是否删除成功
public E remove(int index)删除指定索引处的元素,返回被删除的元素
public E set(int index,E element)修改指定索引处的元素,返回被修改的元素
public E get(int index)返回指定索引处的元素
public int size()返回集合中的元素的个数
11.5.2.3 示例代码
public class ArrayListDemo02 {public static void main(String[] args) {//创建集合ArrayList<String> array = new ArrayList<String>();//添加元素array.add("hello");array.add("world");array.add("java");//public boolean remove(Object o):删除指定的元素,返回删除是否成功//        System.out.println(array.remove("world"));//        System.out.println(array.remove("javaee"));//public E remove(int index):删除指定索引处的元素,返回被删除的元素//        System.out.println(array.remove(1));//IndexOutOfBoundsException//        System.out.println(array.remove(3));//public E set(int index,E element):修改指定索引处的元素,返回被修改的元素//        System.out.println(array.set(1,"javaee"));//IndexOutOfBoundsException//        System.out.println(array.set(3,"javaee"));//public E get(int index):返回指定索引处的元素//        System.out.println(array.get(0));//        System.out.println(array.get(1));//        System.out.println(array.get(2));//System.out.println(array.get(3)); //?????? 自己测试//public int size():返回集合中的元素的个数System.out.println(array.size());//输出集合System.out.println("array:" + array);}
}
11.5.3 ArrayList存储字符串并遍历
11.5.3.1 案例需求

​ 创建一个存储字符串的集合,存储3个字符串元素,使用程序实现在控制台遍历该集合

11.5.3.2 代码实现
public class ArrayListDemo3 {public static void main(String[] args) {//1.创建集合对象ArrayList<String> list = new ArrayList<>();//2.添加元素list.add("aaa");list.add("bbb");list.add("ccc");list.add("ddd");//3.遍历//快捷键: list.fori 正向遍历//list.forr 倒着遍历System.out.print("[");for (int i = 0; i < list.size(); i++) {//i 依次表示集合里面的每一个索引if(i == list.size() - 1){//最大索引System.out.print(list.get(i));}else{//非最大索引System.out.print(list.get(i) + ", ");}}System.out.print("]");}
}
11.5.4 ArrayList存储学生对象并遍历
11.5.4.1 案例需求

​ 创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合

11.5.4.2 代码实现
public class ArrayListDemo4 {public static void main(String[] args) {//1.创建集合对象,用来存储数据ArrayList<Student> list = new ArrayList<>();//2.创建学生对象Student s1 = new Student("zhangsan",16);Student s2 = new Student("lisi",15);Student s3 = new Student("wangwu",18);//3.把学生对象添加到集合中list.add(s1);list.add(s2);list.add(s3);//4.遍历for (int i = 0; i < list.size(); i++) {//i 依次表示集合中的每一个索引Student stu = list.get(i);System.out.println(stu.getName() + ", " + stu.getAge());}}
}
11.5.5 查找用户的索引

需求:

1,main方法中定义一个集合,存入三个用户对象。

用户属性为:id,username,password

2,要求:定义一个方法,根据id查找对应的学生信息。

如果存在,返回索引

如果不存在,返回-1

代码示例:

public class ArrayListDemo6 {public static void main(String[] args) {/*需求:1,main方法中定义一个集合,存入三个用户对象。用户属性为:id,username,password2,要求:定义一个方法,根据id查找对应的学生信息。如果存在,返回索引如果不存在,返回-1*///1.创建集合对象ArrayList<User> list = new ArrayList<>();//2.创建用户对象User u1 = new User("heima001", "zhangsan", "123456");User u2 = new User("heima002", "lisi", "1234");User u3 = new User("heima003", "wangwu", "1234qwer");//3.把用户对象添加到集合当中list.add(u1);list.add(u2);list.add(u3);//4.调用方法,通过id获取对应的索引int index = getIndex(list, "heima001");System.out.println(index);}//1.我要干嘛?  根据id查找对应的学生信息//2.我干这件事情需要什么才能完成?   集合 id//3.方法的调用处是否需要继续使用方法的结果?//要用必须返回,不要用可以返回也可以不返回//明确说明需要有返回值 intpublic static int getIndex(ArrayList<User> list, String id) {//遍历集合得到每一个元素for (int i = 0; i < list.size(); i++) {User u = list.get(i);String uid = u.getId();if(uid.equals(id)){return i;}}//因为只有当集合里面所有的元素都比较完了,才能断定id是不存在的。return -1;}
}
11.5.6 判断用户的是否存在
public class ArrayListDemo5 {public static void main(String[] args) {/* 需求:1,main方法中定义一个集合,存入三个用户对象。用户属性为:id,username,password2,要求:定义一个方法,根据id查找对应的学生信息。如果存在,返回true如果不存在,返回false*///1.定义集合ArrayList<User> list = new ArrayList<>();//2.创建对象User u1 = new User("heima001","zhangsan","123456");User u2 = new User("heima002","lisi","12345678");User u3 = new User("heima003","wangwu","1234qwer");//3.把用户对象添加到集合当中list.add(u1);list.add(u2);list.add(u3);//4.调用方法,查询id是否存在boolean result = contains(list, "heima001");System.out.println(result);}//定义在测试类中的方法需要加static//1.我要干嘛? 我要根据id查询学生是否存在//2.我干这件事情,需要什么才能完成? 集合 id//3.方法的调用处是否需要使用方法的结果?//如果要用,必须返回,如果不用,可以返回也可以不返回//但是本题明确说明需要返回public static boolean contains(ArrayList<User> list, String id){//循环遍历集合,得到集合里面的每一个元素//再进行判断for (int i = 0; i < list.size(); i++) {//i 索引  list.get(i); 元素User u = list.get(i);//判断id是否存在,我是拿着谁跟谁比较//需要把用户对象里面的id拿出来再进行比较。String uid = u.getId();if(id.equals(uid)){return true;//return 关键字:作用就是结束方法。}}//只有当集合里面所有的元素全部比较完毕才能认为是不存在的。return false;}}

11.6 LinkedList集合的特有功能

  • 特有方法

    方法名说明
    public void addFirst(E e)在该列表开头插入指定的元素
    public void addLast(E e)将指定的元素追加到此列表的末尾
    public E getFirst()返回此列表中的第一个元素
    public E getLast()返回此列表中的最后一个元素
    public E removeFirst()从此列表中删除并返回第一个元素
    public E removeLast()从此列表中删除并返回最后一个元素
  • 示例代码

    public class MyLinkedListDemo4 {public static void main(String[] args) {LinkedList<String> list = new LinkedList<>();list.add("aaa");list.add("bbb");list.add("ccc");
    //        public void addFirst(E e)	在该列表开头插入指定的元素//method1(list);//        public void addLast(E e)	将指定的元素追加到此列表的末尾//method2(list);//        public E getFirst()		返回此列表中的第一个元素
    //        public E getLast()		返回此列表中的最后一个元素//method3(list);//        public E removeFirst()		从此列表中删除并返回第一个元素
    //        public E removeLast()		从此列表中删除并返回最后一个元素//method4(list);}private static void method4(LinkedList<String> list) {String first = list.removeFirst();System.out.println(first);String last = list.removeLast();System.out.println(last);System.out.println(list);}private static void method3(LinkedList<String> list) {String first = list.getFirst();String last = list.getLast();System.out.println(first);System.out.println(last);}private static void method2(LinkedList<String> list) {list.addLast("www");System.out.println(list);}private static void method1(LinkedList<String> list) {list.addFirst("qqq");System.out.println(list);}
    }
    

11.7 Set集合

11.7.1 Set集合概述和特点
  • 不可以存储重复元素
  • 没有索引,不能使用普通for循环遍历
11.7.2 Set集合的使用

存储字符串并遍历

public class MySet1 {public static void main(String[] args) {//创建集合对象Set<String> set = new TreeSet<>();//添加元素set.add("ccc");set.add("aaa");set.add("aaa");set.add("bbb");//        for (int i = 0; i < set.size(); i++) {
//            //Set集合是没有索引的,所以不能使用通过索引获取元素的方法
//        }//遍历集合Iterator<String> it = set.iterator();while (it.hasNext()){String s = it.next();System.out.println(s);}System.out.println("-----------------------------------");for (String s : set) {System.out.println(s);}}
}

11.8 TreeSet集合

11.8.1 TreeSet集合概述和特点
  • 不可以存储重复元素
  • 没有索引
  • 可以将元素按照规则进行排序
    • TreeSet():根据其元素的自然排序进行排序
    • TreeSet(Comparator comparator) :根据指定的比较器进行排序
11.8.2 TreeSet集合基本使用

存储Integer类型的整数并遍历

public class TreeSetDemo01 {public static void main(String[] args) {//创建集合对象TreeSet<Integer> ts = new TreeSet<Integer>();//添加元素ts.add(10);ts.add(40);ts.add(30);ts.add(50);ts.add(20);ts.add(30);//遍历集合for(Integer i : ts) {System.out.println(i);}}
}
11.8.3 自然排序Comparable的使用
  • 案例需求

    • 存储学生对象并遍历,创建TreeSet集合使用无参构造方法
    • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
  • 实现步骤

    1. 使用空参构造创建TreeSet集合
      • 用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的
    2. 自定义的Student类实现Comparable接口
      • 自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(T o)方法
    3. 重写接口中的compareTo方法
      • 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
  • 代码实现

    学生类

    public class Student implements Comparable<Student>{private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic int compareTo(Student o) {//按照对象的年龄进行排序//主要判断条件: 按照年龄从小到大排序int result = this.age - o.age;//次要判断条件: 年龄相同时,按照姓名的字母顺序排序result = result == 0 ? this.name.compareTo(o.getName()) : result;return result;}
    }
    

    测试类

    public class MyTreeSet2 {public static void main(String[] args) {//创建集合对象TreeSet<Student> ts = new TreeSet<>();//创建学生对象Student s1 = new Student("zhangsan",28);Student s2 = new Student("lisi",27);Student s3 = new Student("wangwu",29);Student s4 = new Student("zhaoliu",28);Student s5 = new Student("qianqi",30);//把学生添加到集合ts.add(s1);ts.add(s2);ts.add(s3);ts.add(s4);ts.add(s5);//遍历集合for (Student student : ts) {System.out.println(student);}}
    }
    
11.8.4 比较器排序Comparator的使用
  • 案例需求

    • 存储老师对象并遍历,创建TreeSet集合使用带参构造方法
    • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
  • 实现步骤

    • 用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的
    • 比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(T o1,T o2)方法
    • 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
  • 代码实现

    老师类

    public class Teacher {private String name;private int age;public Teacher() {}public Teacher(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Teacher{" +"name='" + name + '\'' +", age=" + age +'}';}
    }
    

    测试类

    public class MyTreeSet4 {public static void main(String[] args) {//创建集合对象TreeSet<Teacher> ts = new TreeSet<>(new Comparator<Teacher>() {@Overridepublic int compare(Teacher o1, Teacher o2) {//o1表示现在要存入的那个元素//o2表示已经存入到集合中的元素//主要条件int result = o1.getAge() - o2.getAge();//次要条件result = result == 0 ? o1.getName().compareTo(o2.getName()) : result;return result;}});//创建老师对象Teacher t1 = new Teacher("zhangsan",23);Teacher t2 = new Teacher("lisi",22);Teacher t3 = new Teacher("wangwu",24);Teacher t4 = new Teacher("zhaoliu",24);//把老师添加到集合ts.add(t1);ts.add(t2);ts.add(t3);ts.add(t4);//遍历集合for (Teacher teacher : ts) {System.out.println(teacher);}}
    }
    
11.8.5 两种比较方式总结
  • 两种比较方式小结
    • 自然排序: 自定义类实现Comparable接口,重写compareTo方法,根据返回值进行排序
    • 比较器排序: 创建TreeSet对象的时候传递Comparator的实现类对象,重写compare方法,根据返回值进行排序
    • 在使用的时候,默认使用自然排序,当自然排序不满足现在的需求时,必须使用比较器排序
  • 两种方式中关于返回值的规则
    • 如果返回值为负数,表示当前存入的元素是较小值,存左边
    • 如果返回值为0,表示当前存入的元素跟集合中元素重复了,不存
    • 如果返回值为正数,表示当前存入的元素是较大值,存右边

11.9 HashSet集合

11.9.1HashSet集合概述和特点
  • 底层数据结构是哈希表
  • 存取无序
  • 不可以存储重复元素
  • 没有索引,不能使用普通for循环遍历
11.9.2HashSet集合的基本应用

存储字符串并遍历

public class HashSetDemo {public static void main(String[] args) {//创建集合对象HashSet<String> set = new HashSet<String>();//添加元素set.add("hello");set.add("world");set.add("java");//不包含重复元素的集合set.add("world");//遍历for(String s : set) {System.out.println(s);}}
}
11.9.3哈希值
  • 哈希值简介

    ​ 是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值

  • 如何获取哈希值

    ​ Object类中的public int hashCode():返回对象的哈希码值

  • 哈希值的特点

    • 同一个对象多次调用hashCode()方法返回的哈希值是相同的
    • 默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同
11.9.4 哈希表结构
  • JDK1.8以前

    ​ 数组 + 链表

  • JDK1.8以后

    • 节点个数少于等于8个

      ​ 数组 + 链表

    • 节点个数多于8个

      ​ 数组 + 红黑树

11.9.5 HashSet集合存储学生对象并遍历
  • 案例需求

    • 创建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合
    • 要求:学生对象的成员变量值相同,我们就认为是同一个对象
  • 代码实现

    学生类

    public class Student {private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;if (age != student.age) return false;return name != null ? name.equals(student.name) : student.name == null;}@Overridepublic int hashCode() {int result = name != null ? name.hashCode() : 0;result = 31 * result + age;return result;}
    }
    

    测试类

    public class HashSetDemo02 {public static void main(String[] args) {//创建HashSet集合对象HashSet<Student> hs = new HashSet<Student>();//创建学生对象Student s1 = new Student("林青霞", 30);Student s2 = new Student("张曼玉", 35);Student s3 = new Student("王祖贤", 33);Student s4 = new Student("王祖贤", 33);//把学生添加到集合hs.add(s1);hs.add(s2);hs.add(s3);hs.add(s4);//遍历集合(增强for)for (Student s : hs) {System.out.println(s.getName() + "," + s.getAge());}}
    }
    
  • 总结

    ​ HashSet集合存储自定义类型元素,要想实现元素的唯一,要求必须重写hashCode方法和equals方法

11.10 Map集合

11.10.1 Map集合概述和特点
  • Map集合概述

    interface Map<K,V>  K:键的类型;V:值的类型
    
  • Map集合的特点

    • 双列集合,一个键对应一个值
    • 键不可以重复,值可以重复
  • Map集合的基本使用

    public class MapDemo01 {public static void main(String[] args) {//创建集合对象Map<String,String> map = new HashMap<String,String>();//V put(K key, V value) 将指定的值与该映射中的指定键相关联map.put("itheima001","林青霞");map.put("itheima002","张曼玉");map.put("itheima003","王祖贤");map.put("itheima003","柳岩");//输出集合对象System.out.println(map);}
    }
    
11.10.2Map集合的基本功能
  • 方法介绍

    方法名说明
    V put(K key,V value)添加元素
    V remove(Object key)根据键删除键值对元素
    void clear()移除所有的键值对元素
    boolean containsKey(Object key)判断集合是否包含指定的键
    boolean containsValue(Object value)判断集合是否包含指定的值
    boolean isEmpty()判断集合是否为空
    int size()集合的长度,也就是集合中键值对的个数
  • 示例代码

    public class MapDemo02 {public static void main(String[] args) {//创建集合对象Map<String,String> map = new HashMap<String,String>();//V put(K key,V value):添加元素map.put("张无忌","赵敏");map.put("郭靖","黄蓉");map.put("杨过","小龙女");//V remove(Object key):根据键删除键值对元素
    //        System.out.println(map.remove("郭靖"));
    //        System.out.println(map.remove("郭襄"));//void clear():移除所有的键值对元素
    //        map.clear();//boolean containsKey(Object key):判断集合是否包含指定的键
    //        System.out.println(map.containsKey("郭靖"));
    //        System.out.println(map.containsKey("郭襄"));//boolean isEmpty():判断集合是否为空
    //        System.out.println(map.isEmpty());//int size():集合的长度,也就是集合中键值对的个数System.out.println(map.size());//输出集合对象System.out.println(map);}
    }
    
11.10.3Map集合的获取功能
  • 方法介绍

    方法名说明
    V get(Object key)根据键获取值
    Set keySet()获取所有键的集合
    Collection values()获取所有值的集合
    Set<Map.Entry<K,V>> entrySet()获取所有键值对对象的集合
  • 示例代码

    public class MapDemo03 {public static void main(String[] args) {//创建集合对象Map<String, String> map = new HashMap<String, String>();//添加元素map.put("张无忌", "赵敏");map.put("郭靖", "黄蓉");map.put("杨过", "小龙女");//V get(Object key):根据键获取值
    //        System.out.println(map.get("张无忌"));
    //        System.out.println(map.get("张三丰"));//Set<K> keySet():获取所有键的集合
    //        Set<String> keySet = map.keySet();
    //        for(String key : keySet) {
    //            System.out.println(key);
    //        }//Collection<V> values():获取所有值的集合Collection<String> values = map.values();for(String value : values) {System.out.println(value);}}
    }
    
11.10.4Map集合的遍历(方式1)
  • 遍历思路

    • 我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
      • 把所有的丈夫给集中起来
      • 遍历丈夫的集合,获取到每一个丈夫
      • 根据丈夫去找对应的妻子
  • 步骤分析

    • 获取所有键的集合。用keySet()方法实现
    • 遍历键的集合,获取到每一个键。用增强for实现
    • 根据键去找值。用get(Object key)方法实现
  • 代码实现

    public class MapDemo01 {public static void main(String[] args) {//创建集合对象Map<String, String> map = new HashMap<String, String>();//添加元素map.put("张无忌", "赵敏");map.put("郭靖", "黄蓉");map.put("杨过", "小龙女");//获取所有键的集合。用keySet()方法实现Set<String> keySet = map.keySet();//遍历键的集合,获取到每一个键。用增强for实现for (String key : keySet) {//根据键去找值。用get(Object key)方法实现String value = map.get(key);System.out.println(key + "," + value);}}
    }
    
11.10.5Map集合的遍历(方式2)
  • 遍历思路

    • 我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
      • 获取所有结婚证的集合
      • 遍历结婚证的集合,得到每一个结婚证
      • 根据结婚证获取丈夫和妻子
  • 步骤分析

    • 获取所有键值对对象的集合
      • Set<Map.Entry<K,V>> entrySet():获取所有键值对对象的集合
    • 遍历键值对对象的集合,得到每一个键值对对象
      • 用增强for实现,得到每一个Map.Entry
    • 根据键值对对象获取键和值
      • 用getKey()得到键
      • 用getValue()得到值
  • 代码实现

    public class MapDemo02 {public static void main(String[] args) {//创建集合对象Map<String, String> map = new HashMap<String, String>();//添加元素map.put("张无忌", "赵敏");map.put("郭靖", "黄蓉");map.put("杨过", "小龙女");//获取所有键值对对象的集合Set<Map.Entry<String, String>> entrySet = map.entrySet();//遍历键值对对象的集合,得到每一个键值对对象for (Map.Entry<String, String> me : entrySet) {//根据键值对对象获取键和值String key = me.getKey();String value = me.getValue();System.out.println(key + "," + value);}}
    }
    

11.11 HashMap集合

11.11.1HashMap集合概述和特点
  • HashMap底层是哈希表结构的
  • 依赖hashCode方法和equals方法保证键的唯一
  • 如果键要存储的是自定义对象,需要重写hashCode和equals方法
11.11.2HashMap集合应用案例
  • 案例需求

    • 创建一个HashMap集合,键是学生对象(Student),值是居住地 (String)。存储多个元素,并遍历。
    • 要求保证键的唯一性:如果学生对象的成员变量值相同,我们就认为是同一个对象
  • 代码实现

    学生类

    public class Student {private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;if (age != student.age) return false;return name != null ? name.equals(student.name) : student.name == null;}@Overridepublic int hashCode() {int result = name != null ? name.hashCode() : 0;result = 31 * result + age;return result;}
    }
    

    测试类

    public class HashMapDemo {public static void main(String[] args) {//创建HashMap集合对象HashMap<Student, String> hm = new HashMap<Student, String>();//创建学生对象Student s1 = new Student("林青霞", 30);Student s2 = new Student("张曼玉", 35);Student s3 = new Student("王祖贤", 33);Student s4 = new Student("王祖贤", 33);//把学生添加到集合hm.put(s1, "西安");hm.put(s2, "武汉");hm.put(s3, "郑州");hm.put(s4, "北京");//遍历集合Set<Student> keySet = hm.keySet();for (Student key : keySet) {String value = hm.get(key);System.out.println(key.getName() + "," + key.getAge() + "," + value);}}
    }
    

11.12 TreeMap集合

11.12.1TreeMap集合概述和特点
  • TreeMap底层是红黑树结构
  • 依赖自然排序或者比较器排序,对键进行排序
  • 如果键存储的是自定义对象,需要实现Comparable接口或者在创建TreeMap对象时候给出比较器排序规则
11.12.2TreeMap集合应用案例
  • 案例需求

    • 创建一个TreeMap集合,键是学生对象(Student),值是籍贯(String),学生属性姓名和年龄,按照年龄进行排序并遍历
    • 要求按照学生的年龄进行排序,如果年龄相同则按照姓名进行排序
  • 代码实现

    学生类

    public class Student implements Comparable<Student>{private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic int compareTo(Student o) {//按照年龄进行排序int result = o.getAge() - this.getAge();//次要条件,按照姓名排序。result = result == 0 ? o.getName().compareTo(this.getName()) : result;return result;}
    }
    

    测试类

    public class Test1 {public static void main(String[] args) {// 创建TreeMap集合对象TreeMap<Student,String> tm = new TreeMap<>();// 创建学生对象Student s1 = new Student("xiaohei",23);Student s2 = new Student("dapang",22);Student s3 = new Student("xiaomei",22);// 将学生对象添加到TreeMap集合中tm.put(s1,"江苏");tm.put(s2,"北京");tm.put(s3,"天津");// 遍历TreeMap集合,打印每个学生的信息tm.forEach((Student key, String value)->{System.out.println(key + "---" + value);});}
    }
    

要求按照学生的年龄进行排序,如果年龄相同则按照姓名进行排序

  • 代码实现

    学生类

    public class Student implements Comparable<Student>{private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic int compareTo(Student o) {//按照年龄进行排序int result = o.getAge() - this.getAge();//次要条件,按照姓名排序。result = result == 0 ? o.getName().compareTo(this.getName()) : result;return result;}
    }
    

    测试类

    public class Test1 {public static void main(String[] args) {// 创建TreeMap集合对象TreeMap<Student,String> tm = new TreeMap<>();// 创建学生对象Student s1 = new Student("xiaohei",23);Student s2 = new Student("dapang",22);Student s3 = new Student("xiaomei",22);// 将学生对象添加到TreeMap集合中tm.put(s1,"江苏");tm.put(s2,"北京");tm.put(s3,"天津");// 遍历TreeMap集合,打印每个学生的信息tm.forEach((Student key, String value)->{System.out.println(key + "---" + value);});}
    }
    

http://www.mrgr.cn/news/59908.html

相关文章:

  • 网络编程_day3
  • 【AI探索实践】使用Docker部署ChatGPT Next Web个人智能助手
  • elselect iphone上 要点两次
  • OCR应用之集装箱箱号自动识别技术,原理与应用
  • CSS揭秘:7. 伪随机背景
  • OpenCV中的图像通道合并
  • 动态规划 —— 斐波那契数列模型-解码方法
  • HarmonyOS NEXT 应用开发实战(八、知乎日报List列表下拉刷新及上滑加载更多分页的实现)
  • 【笔记】Diffusion Model 扩散过程(熵增过程:从有序变为无序):在原始分布上逐步的加高斯噪声,加到最后这个分布就变成一个各项独立的高斯分布
  • 常用 Web 框架
  • 我的电脑问题
  • 使用openssl验证https配置的ssl证书是否可以正常访问
  • Mybatis-plus-扩展功能
  • linux中级(NFS服务器)
  • Linux TCP CC状态机
  • Puppeteer 与浏览器版本兼容性:自动化测试的最佳实践
  • uniapp实现与webview之间的相互通讯
  • Vue项目GET请求正常,POST请求却失效?揭秘Mock服务背后的故事
  • 创建WBS项目管理过程
  • 不小心drop column了一个列,真的凉凉了吗?
  • linux驱动-引入pinctrl子系统
  • 离散化步骤
  • 群控系统服务端开发模式-应用开发-业务架构逻辑开发BaseAPI
  • 企业信息化与数字化 - 信息化是基础,数字化是未来
  • 动态规划-子序列问题——1218.最长定差子序列
  • VS Code 代码提示 重叠 显示不全