1. 回顾
1. 集合: 理解为容器--它的长度可以变大的,而且它存储的都是对象类型。 2. List:----->它是一个接口,该集合中的元素可以重复,而且是有序的(有下标)。 ArrayList--->它的底层是数组结构,它的查询效率高,但是它的添加和删除效率低--因为它要牵涉到数据的迁移。 常见方法: add();size();indexOf(); contains(); get();remove();isEmpty(); LinkedList--->底层双向链表结构,它增加和删除效率高,但是它的查询效率低。 常见的方法: 它的方法和ArrayList中的方法比较相似,它也有自己特有的方法: addFirst() addLast() getFirst() getLast()
2. 正文
1. LinkedList的底层源码。 2. Set集合 3. HashSet 4. TreeSet 5. Map集合 6. HashMap 6. TreeMap
3.LinkedList的底层源码。
1.凡是查询源码 ,我们都是从类的构造方法入手: /** * Constructs an empty list. */ public LinkedList() { } 该类的构造方法内是空的,没有任何的代码。 但是该类中有三个属性。 transient int size = 0; //索引 transient Node<E> first; //第一个元素对象 transient Node<E> last; //表示最后一个元素对象。 ================ add的源码=====E:理解为Object类型==========================。 public boolean add(E e) { linkLast(e); return true; } void linkLast(E e) { final Node<E> l = last; //上一个节点 数据 下一个节点 final Node<E> newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; } ==================Node的源码 内部类======================================= private static class Node<E> { //<E>泛型--object E item; //数据 Node<E> next; //下一个节点 Node<E> prev; //上一个节点 Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } }
1、==================== get(1)-----获取元素======================== public E get(int index) { checkElementIndex(index); //检查index下标是否正确。 return node(index).item; //李四Node对象 } ========================node(index)============================= Node<E> node(int index) { //>> 位运算二进制运算 ----- size >> 1 一半的意思size/2 if (index < (size >> 1)) { //前半部分 Node<E> x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else { //后半部分 Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } }
分析: LinkedList查询效率低。因为它要一个节点一个节点的往后找。
4. Set集合
4.1 HashSet集合
4.1.1 创建HashSet对象。
public class Test02 { public static void main(String[] args) { HashSet hashSet= new HashSet(); HashSet hashSet1 = new HashSet(16);//初始容器的大小 //loadFactor:--->0.7f 表示负载因子 当空间使用70%时 要求扩容 HashSet hashSet2 = new HashSet(16,0.7f); } }
4.1.2 添加元素
//添加操作 hashSet.add("java01"); hashSet.add("java02"); hashSet.add("java04"); hashSet.add("java03"); hashSet.add("java02"); HashSet set2=new HashSet(); set2.add("刘德华"); set2.add("张学友"); set2.add("黎明"); hashSet.addAll(set2); //把set2中的每个元素添加到hashset中 System.out.println(hashSet); //元素不能重复 而且无序
4.1.3 删除
//删除 hashSet.remove("黎明"); // hashSet.clear();//清空容器集合 System.out.println(hashSet);
4.1.4 修改
//修改操作 boolean empty = hashSet.isEmpty(); //判断是否为空 System.out.println(empty); boolean b = hashSet.contains("刘德华");//判断元素是否在容器中 System.out.println(b);
4.1.5 hashSet的遍历
(1)通过foreach遍历
//遍历--- foreach for(Object o: hashSet){ System.out.println(o); }
(2)通过迭代器来遍历
//迭代器遍历 Iterator iterator = hashSet.iterator();//获取迭代器对象 有序:有下标 while (iterator.hasNext()){//判断是否指定能够移动 Object next = iterator.next();//指定移动并获取当前的元素 System.out.println(next); }
4.1.6 hashSet的源码
从构造函数说起: /** * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has * default initial capacity (16) and load factor (0.75). */ public HashSet() { map = new HashMap<>(); } 在创建一个HashSet的对象时,底层创建的是HashMap。我们说hashset的底层原理时,我们就在后HashMap的原理就行。 讲HashMap时给大家说原理。
4.2 TreeSet集合。
TreeSet中的方法和HashSet中的方法一模一样 只是他们的实现不一样。 TreeSet 基于TreeMap 实现。TreeSet可以实现有序集合,但是有序性需要通过比较器实现。
例子: 存储String类型。
TreeSet treeSet=new TreeSet(); treeSet.add("java05"); treeSet.add("java03"); treeSet.add("java04"); treeSet.add("java01"); treeSet.add("java02"); treeSet.add("java04"); System.out.println(treeSet);
存储一个对象类型:
public class Test04 { public static void main(String[] args) { TreeSet treeSet=new TreeSet(); treeSet.add(new Student("王俊凯",17)); treeSet.add(new Student("赵晓普",16)); treeSet.add(new Student("赵俊涛",16)); treeSet.add(new Student("闫克起",15)); System.out.println(treeSet); } }
通过运行我们发现出现如下的错误:
发现: TreeSet中的元素必须实现Comparable接口 方可放入TreeSet
解决办法有两个:
第一个: 让你的类实现Comparable接口
package com.ykq; import java.util.TreeSet; /** * @program: day03 * @description: * @author: 闫克起2 * @create: 2022-04-16 15:59 **/ public class Test04 { public static void main(String[] args) { TreeSet treeSet=new TreeSet(); //TreeSet不允许重复元素 treeSet.add(new Student("王俊凯",17)); treeSet.add(new Student("赵晓普",16)); treeSet.add(new Student("赵俊涛",16)); treeSet.add(new Student("闫克起",15)); System.out.println(treeSet); } } class Student implements Comparable{ private String name; private Integer age; @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } public Student(String name, Integer age) { this.name = name; this.age = age; } public Student() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } //排序:---返回如果大于0 表示当前元素比o大 如果返回-1 当前添加的元素比o小 返回0表示相同元素。 @Override public int compareTo(Object o) { Student student= (Student) o; System.out.println(this+"===================>"+o); if(this.age>student.age){ return 1; } if(this.age<student.age){ return -1; } return 0; } }
第二种: 在创建TreeSet时指定排序的对象。
作业: 把今天讲的练习3遍---> 集合的论坛继续补充。