1. 学习内容
集合框架的体系
List集合以及相关类
泛型详解
Set集合以及相关类
Map集合以及相关类
集合的遍历和迭代器
比较器的使用
集合工具类
2. 学习目标
集合框架的体系-->理解
List集合以及相关类-> 掌握
ArrayList-->掌握
LinkedList-->掌握
Vector-->掌握
泛型详解
集合中使用泛型-->掌握
自定义泛型-->掌握
Set集合以及相关类
HashSet-->熟悉
LinkedHasSet-->熟悉
TreeSet-->熟悉
Map集合以及相关类
HashMap-->掌握
LinkedHashMap-->熟悉
HashTable-->熟悉
TreeMap-->熟悉
HashMap源码分析
集合的遍历和迭代器-->掌握
比较器的使用-->熟悉
集合工具类-->熟悉
3. 课堂笔记
1. 集合
1. 集合的介绍
在编程中会经常使用数据用于存储,以及交互,如果我们存储时需要存储多个数据则能够使用的较少(数组),然而数组他的缺点很多,在使用时非常麻烦 所以Java又提供了集合的概念,集合与数组相同都是用于存储多个数据(元素),但是不同点在于集合属于引用数据类型,集合使用时提供的方法更多,使用起来更加简单
数组的缺点:增删慢,一旦初始化长度则无法改变(Arrays的方法可以改),只能存储同一种类型,空间一旦确定就是在内存开辟所有空间占用较多,数组操作不方便 数组的优点:查询速度快(通过小标索引直接获取元素),是一种简单的线性序列,数组存储非常简单 集合的出现解决了很多数组存在的问题,例如占用空间多,长度不能更改,增删慢,查询快,还提供了非常多操作数据的方法使用起来更加方便 并且集合有很多种,根据不同需求使用不同的集合也能够解决很大的问题 集合分为两大类
存储单数据-->Collection集合
存储双数据-->Map集合
2. 集合的体系结构
体系结构类似于族谱,会从最顶部(祖宗)向下延伸(子孙),结构体系就是继承(实现)关系,存在父子关系就形成体系结构,体系结构只需要看具体的实现类 体系结构中一般祖宗提供的仅仅只是血统(程序中的方法),子孙类只需要继承(实现)祖宗的方法重写即可
1. Collection集合体系
下图为Collection集合体系,其中包含List集合以及Set集合,以及其子孙类
转存失败
重新上
2. Map集合体系
下图为Map集合体系结构,其中包含直接子类
2. Collection接口(重点)`
Collection接口概述
Collection接口是集合祖先类(超类),其中定义了最初的通用方法,并且子孙类都会实现,Collection接口使用的较少,一般都是直接使用其子孙
1. Collection接口
1. Collection常用方法
boolean add(E e);
:向集合中添加新的元素
boolean addAll(Collection<? extends E> c);
:向集合中添加c集合的所有元素,将c集合中的所有元素添加到此集合中
c:Collection以及子孙类都可以,集合参数
boolean remove(Object o);
:从集合中移除指定元素
boolean removeAll(Collection<?> c);
:从集合中移除c集合的所有相同元素
void clear();
:清空集合(将所有元素删除)
boolean contains(Object o);
:判断集合中是否包含指定元素
boolean containsAll(Collection<?> c);
:判断集合中是否包含指定集合的元素
boolean equals(Object o);
:判断集合是否相同
boolean isEmpty();
:判断集合是否为空(不是null)
Iterator<E> iterator();
:返回集合可迭代对象
Object[] toArray();
:将集合转为数组
int size();
:返回集合长度(元素数量)
default Stream<E> stream()
:返回集合的Stream流2. List接口(重点)
1. List接口概述
List接口是一个有序的并且可重复,以及值可为null的集合,也可以称之为
序列
有序:存储顺序与取出顺序一致,并且可以通过下标索引直接获取元素 可重复:存储的元素允许出现重复的,并且支持存储null数据 List接口是Collection接口的直接子接口,其中添加了一些新的方法,以及原本Collection接口的方法同样也拥有2. List接口常用方法
void add(int index, E element);
:向集合中指定位置插入元素
boolean addAll(int index, Collection<? extends E> c);
:向集合中指定位置插入c集合的所有元素
E get(int index);
:获取集合中指定位置的元素
int indexOf(Object o);
:判断集合中是否存在指定元素(只判断第一次出现的),并返回此元素的下标索引位置,如果没有找到则返回-1
int lastIndexOf(Object o);
:判断集合中是否存在指定元素(只判断最后一次出点的),并返回此元素的下标索引位置,如果没有找到则返回-1
E remove(int index);
:通过下标索引删除集合中的元素
E set(int index, E element);
:修改指定下标索引的元素
default void sort(Comparator<? super E> c)
:通过比较器给集合排序
List<E> subList(int fromIndex, int toIndex);
:通过指定起始位置以及结束位置裁剪集合由于List是接口,无法创建对象,所以无法直接使用,只能通过其子孙类使用
2. List接口实现类之ArrayList类(重点)
1. ArrayList类概述
ArrayList是List接口的直接实现子类,其中完美的重写了所有List接口的方法 ArrayList底层是使用
动态数组
实现(通过Arrays工具类实现的动态数组),动态数组是指数组长度可以动态扩容 ArrayList有数组除了不可变长度之外的所有优缺点 ArrayList是通过Object存储数组数据2. ArrayList构造方法
// 通过无参构造方法创建ArrayList对象 public ArrayList() { // 初始化ArrayList数组对象 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } // 通过带参构造方法指定初始化容量创建ArrayList对象 public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } // 通过带参构造方法指定集合创建ArrayList对象 public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } }3. ArrayList常用方法
boolean add(E e);
:向集合中添加新的元素
void add(int index, E element);
:向集合中指定位置插入元素
boolean addAll(Collection<? extends E> c);
:向集合中添加c集合的所有元素,将c集合中的所有元素添加到此集合中
c:Collection以及子孙类都可以,集合参数
boolean addAll(int index, Collection<? extends E> c);
:向集合中指定位置插入c集 合的所有元素
E get(int index);
:获取集合中指定位置的元素
boolean contains(Object o);
:判断集合中是否包含指定元素
boolean containsAll(Collection<?> c);
:判断集合中是否包含指定集合的元素
int indexOf(Object o);
:判断集合中是否存在指定元素(只判断第一次出现的),并返回此元素的下标索引位置,如果没有找到则返回-1
int lastIndexOf(Object o);
:判断集合中是否存在指定元素(只判断最后一次出点的),并返回此元素的下标索引位置,如果没有找到则返回-1
boolean remove(Object o);
:从集合中移除指定元素
E remove(int index);
:通过下标索引删除集合中的元素
boolean removeAll(Collection<?> c);
:从集合中移除c集合的所有相同元素
E set(int index, E element);
:修改指定下标索引的元素
default void sort(Comparator<? super E> c)
:通过比较器给集合排序
List<E> subList(int fromIndex, int toIndex);
:通过指定起始位置以及结束位置裁剪集合
boolean equals(Object o);
:判断集合是否相同
Object[] toArray();
:将集合转为数组
int size();
:返回集合长度(元素数量)
void clear();
:清空集合(将所有元素删除)
boolean isEmpty();
:判断集合是否为空(不是null)
Iterator<E> iterator();
:返回集合可迭代对象
default Stream<E> stream()
:返回集合的Stream流4. ArrayList代码案例
public class Demo { public static void main(String[] args) { // 创建ArrayList对象 ArrayList arrayList = new ArrayList(); // 1. `boolean add(E e);`:向集合中添加新的元素 System.out.println("========================add========================"); arrayList.add("梅超风"); arrayList.add(1234); arrayList.add("天山童姥"); arrayList.add("肾虚公子"); arrayList.add("吴签"); arrayList.add(12.34); arrayList.add(true); System.out.println(arrayList); // 2. `void add(int index, E element);`:向集合中指定位置插入元素 arrayList.add(0, "基尼太美"); System.out.println(arrayList); // 3. `boolean addAll(Collection<? extends E> c);`:向集合中添加c集合的所有元素,将c集合中的所有元素添加到此集合中 // 1. c:Collection以及子孙类都可以,集合参数 System.out.println("========================addAll========================"); arrayList.addAll(arrayList); System.out.println(arrayList); // 4. `boolean addAll(int index, Collection<? extends E> c);`:向集合中指定位置插入c集合的所有元素 System.out.println("========================addAll========================"); arrayList.addAll(1, arrayList); System.out.println(arrayList); // 5. `E get(int index);`:获取集合中指定位置的元素 // 如果下标索引超出元素数量则抛下标索引越界异常 System.out.println("========================get========================"); Object value = arrayList.get(0); System.out.println(value); // 6. `boolean contains(Object o);`:判断集合中是否包含指定元素 System.out.println("========================contains========================"); boolean isContains = arrayList.contains("基尼太美"); System.out.println(isContains); // 7. `boolean containsAll(Collection<?> c);`:判断集合中是否包含指定集合的元素 System.out.println("========================containsAll========================"); boolean containsAll = arrayList.containsAll(arrayList); System.out.println(containsAll); // 8. `int indexOf(Object o);`:判断集合中是否存在指定元素(只判断第一次出现的),并返回此元素的下标索引位置,如果没有找到则返回-1 System.out.println("========================indexOf========================"); int indexOf = arrayList.indexOf("基尼太美"); System.out.println(indexOf); indexOf = arrayList.indexOf("基尼太美哦哦哦哦哦"); System.out.println(indexOf); // 9. `int lastIndexOf(Object o);`:判断集合中是否存在指定元素(只判断最后一次出点的),并返回此元素的下标索引位置,如果没有找到则返回-1 System.out.println("========================lastIndexOf========================"); int lastIndexOf = arrayList.lastIndexOf("基尼太美"); System.out.println(lastIndexOf); lastIndexOf = arrayList.lastIndexOf("基尼太美哦哦哦哦哦"); System.out.println(lastIndexOf); // 10. `boolean remove(Object o);`:从集合中移除指定元素 System.out.println("========================remove========================"); boolean isRemove = arrayList.remove("基尼太美"); System.out.println(isRemove); isRemove = arrayList.remove("基尼太美123"); System.out.println(isRemove); System.out.println(arrayList); // 11. `E remove(int index);`:通过下标索引删除集合中的元素 System.out.println("========================remove========================"); Object remove = arrayList.remove(2); System.out.println(remove); System.out.println(arrayList); // 12. `boolean removeAll(Collection<?> c);`:从集合中移除c集合的所有相同元素 System.out.println("========================removeAll========================"); boolean removeAll = arrayList.removeAll(arrayList); System.out.println(removeAll); System.out.println(arrayList); arrayList.add("梅超风"); arrayList.add(1234); arrayList.add("天山童姥"); arrayList.add("肾虚公子"); arrayList.add("吴签"); arrayList.add(12.34); arrayList.add(true); // 13. `E set(int index, E element);`:修改指定下标索引的元素 System.out.println("========================set========================"); Object set = arrayList.set(1, 5678); System.out.println(set); System.out.println(arrayList); // 14. `default void sort(Comparator<? super E> c)`:通过比较器给集合排序 System.out.println("========================sort========================"); // 15. `List<E> subList(int fromIndex, int toIndex);`:通过指定起始位置以及结束位置裁剪集合 System.out.println("========================subList========================"); List list = arrayList.subList(3, 4); System.out.println(list); // 16. `boolean equals(Object o);`:判断集合是否相同 System.out.println("========================equals========================"); boolean equals = arrayList.equals(list); System.out.println(equals); equals = arrayList.equals(arrayList); System.out.println(equals); // 17. `Object[] toArray();`:将集合转为数组 System.out.println("========================toArray========================"); Object[] objects = arrayList.toArray(); System.out.println(Arrays.toString(objects)); // 18. `int size();`:返回集合长度(元素数量) System.out.println("========================size========================"); int size = arrayList.size(); System.out.println(size); // 19. `void clear();`:清空集合(将所有元素删除) System.out.println("========================clear========================"); arrayList.clear(); System.out.println(arrayList); // 20. `boolean isEmpty();`:判断集合是否为空(不是null) System.out.println("========================isEmpty========================"); boolean empty = arrayList.isEmpty(); System.out.println(empty); arrayList.add("基尼太美"); System.out.println(arrayList); empty = arrayList.isEmpty(); System.out.println(empty); } }3. List接口实现类之LinkedList类(熟悉)
1. LinkedList概述
LinkedList与ArrayList相同是List接口的直接实现子类,但是区别在于底层实现,ArrayList使用的是动态数组实现,LinkedList底层是使用双链表结构实现 双链表结构的优缺点,链表不同于数组,存储数据时不需要连续的空间,并且不需要初始化容量,在删除以及新增是速度飞快,但是查询的速度慢(原因是他没有下标索引) LinkedList与ArrayList正好是相反的作用
1. 链表是什么,分为几种
链表概述,链表是非连续空间,数据的存储关联是由对象指向下一个存储空间的内存地址来查找,他的长度是可以无限增涨并且不会出现浪费空间的情况 一般链表最低需要两个元素,两个元素代表一个存储单元,存储单元中分为
元素
以及next
(指针,指向下一个元素) 链表分为几种:1. 单链表结构,2. 双链表结构,3. 循环单链表结构,4. 循环双链表结构
单链表结构存储方式
单链表存储方式,是有一个存储单元组成,一个存储单元中存在两个数据,数据1:存储元素,数据2:存储指向下一个单元的内存地址
存储单元一般被称之为
node
节点,存储元素的小单元为称之为data
,存储下一个节点的数据的一般呗称之为next
(指针)第一个Node节点对象为首节点,最后一个Node节点对象为尾结点
双链表结构存储方式
双链表结构是单链表的升级版本,单链表只会指向后一个Node节点对象,双链表则前后会指向,丛任意一个位置都可向前或向后查询元素,但是首节点不能向前尾结点不能向后
双链表结构:分为三个部分;1. prev:指向前一个节点对象,2. data:存储的元素数据,3. next:指向下一个节点对象
双链表第一个Node节点为首节点,最后一个Node节点为尾结点,首节点prev指向null,尾结点next也指向null
环形单链表存储方式
环形单链表与单链表相同,唯一的却别是尾结点重新指向首节点,则可以无限循环查询
环形单链表与单链表存储单元相同,分为1. data:存储元素数据,2. next:存储下一个节点地址
环形双链表存储方式
环形双链表与双链表结构相同,唯一的却别在于首节点的prev不在指向null,而是指向尾结点,相同尾结点的next不在指向null,而是指向首节点
环形双链表存储单元分为3个,1. prev:指向前一个节点,2. data:存储元素数据,3. next:指向下一个节点
环形双链表结构首节点的prev指向尾结点,尾结点的next指向首节点,形成环状
LinkedList就是以双链表为主实现的集合,存储数据时就是通过节点对象为单元存储,存储对象被命名为Node节点,Node节点对象中有三个属性,第一个属性是prev是Node类型用于存储上一个节点对象,第二个属性是item是用于存储数据,第三个属性是next是Node类型,用于存储下一个节点对象 LinkedList的Node节点实现-->LinkedList的底层数据存储格式
// Node节点类 private static class Node<E> { // item就是data用于存储数据 E item; // next就是指向下一个节点对象地址 Node<E> next; // prev就是指向上一个节点对象地址 Node<E> prev; // Node节点对象构造方法 Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } }2. LinkedList构造方法
// 空参构造方法用于创建LinkedList对象 public LinkedList() { } // 将指定集合元素添加到LinkedList对象中并创建LinkedList对象 public LinkedList(Collection<? extends E> c) { // 当前空参构造方法 this(); // 调用自身方法addAll添加所有数据 addAll(c); }3. LinkedList常用方法
boolean add(E e);
:向集合中添加新的元素
void add(int index, E element);
:向集合中指定位置插入元素
boolean addAll(Collection<? extends E> c);
:向集合中添加c集合的所有元素,将c集合中的所有元素添加到此集合中
c:Collection以及子孙类都可以,集合参数
boolean addAll(int index, Collection<? extends E> c);
:向集合中指定位置插入c集合的所有元素
E get(int index);
:获取集合中指定位置的元素
boolean contains(Object o);
:判断集合中是否包含指定元素
boolean containsAll(Collection<?> c);
:判断集合中是否包含指定集合的元素
int indexOf(Object o);
:判断集合中是否存在指定元素(只判断第一次出现的),并返回此元素的下标索引位置,如果没有找到则返回-1
int lastIndexOf(Object o);
:判断集合中是否存在指定元素(只判断最后一次出点的),并返回此元素的下标索引位置,如果没有找到则返回-1
boolean remove(Object o);
:从集合中移除指定元素
E remove(int index);
:通过下标索引删除集合中的元素
boolean removeAll(Collection<?> c);
:从集合中移除c集合的所有相同元素
E set(int index, E element);
:修改指定下标索引的元素
default void sort(Comparator<? super E> c)
:通过比较器给集合排序
List<E> subList(int fromIndex, int toIndex);
:通过指定起始位置以及结束位置裁剪集合
boolean equals(Object o);
:判断集合是否相同
Object[] toArray();
:将集合转为数组
int size();
:返回集合长度(元素数量)
void clear();
:清空集合(将所有元素删除)
boolean isEmpty();
:判断集合是否为空(不是null)
Iterator<E> iterator();
:返回集合可迭代对象
default Stream<E> stream()
:返回集合的Stream流
public void addFirst(E e)
:在首部插入元素
public void addLast(E e)
:在尾部添加元素
public E getFirst()
:获取第一个节点元素
public E getLast()
:获取最后一个节点元素
public E removeFirst()
:移除第一个节点元素
public E removeLast()
:移除最后一个节点元素
public boolean offerFirst(E e)
:将指定元素插入到列表开头
public boolean offerLast(E e)
:将指定元素插入到列表结尾
public E peekFirst()
:获取首节点元素,但是不删除
public E peekLast()
:获取尾结点元素,但是不删除
public E pollFirst()
:获取首节点元素,并删除
public E pollLast()
:获取尾结点元素,并删除4. LinkedList代码案例
public class Demo { public static void main(String[] args) { // 创建LinkedList对象 LinkedList linkedList = new LinkedList(); // 1. `boolean add(E e);`:向集合中添加新的元素 System.out.println("=============================add============================="); linkedList.add("彭于晏"); linkedList.add("梅超风"); linkedList.add("基尼太美"); linkedList.add("灭绝师太"); linkedList.add("裘千仞"); linkedList.add("裘千尺"); linkedList.add(1.23); System.out.println(linkedList); // 2. `void add(int index, E element);`:向集合中指定位置插入元素 System.out.println("=============================add============================="); linkedList.add(1, "李莫愁"); System.out.println(linkedList); // 3. `boolean addAll(Collection<? extends E> c);`:向集合中添加c集合的所有元素,将c集合中的所有元素添加到此集合中 System.out.println("=============================add============================="); // 4. `boolean addAll(int index, Collection<? extends E> c);`:向集合中指定位置插入c集合的所有元素 System.out.println("=============================add============================="); // 5. `E get(int index);`:获取集合中指定位置的元素 System.out.println("=============================get============================="); Object value = linkedList.get(0); System.out.println(value); // 6. `boolean contains(Object o);`:判断集合中是否包含指定元素 System.out.println("=============================contains============================="); boolean isContains = linkedList.contains("彭于晏"); System.out.println(isContains); // 7. `boolean containsAll(Collection<?> c);`:判断集合中是否包含指定集合的元素 System.out.println("=============================add============================="); // 8. `int indexOf(Object o);`:判断集合中是否存在指定元素(只判断第一次出现的),并返回此元素的下标索引位置,如果没有找到则返回-1 System.out.println("=============================add============================="); // 9. `int lastIndexOf(Object o);`:判断集合中是否存在指定元素(只判断最后一次出点的),并返回此元素的下标索引位置,如果没有找到则返回-1 System.out.println("=============================add============================="); // 10. `boolean remove(Object o);`:从集合中移除指定元素 System.out.println("=============================remove============================="); Object remove = linkedList.remove(1.23); System.out.println(remove); System.out.println(linkedList); // 11. `E remove(int index);`:通过下标索引删除集合中的元素 System.out.println("=============================remove============================="); Object remove1 = linkedList.remove(2); System.out.println(remove1); System.out.println(linkedList); // 12. `boolean removeAll(Collection<?> c);`:从集合中移除c集合的所有相同元素 System.out.println("=============================add============================="); // 13. `E set(int index, E element);`:修改指定下标索引的元素 System.out.println("=============================set============================="); Object set = linkedList.set(3, "胖头陀"); System.out.println(set); System.out.println(linkedList); // 14. `default void sort(Comparator<? super E> c)`:通过比较器给集合排序 System.out.println("=============================add============================="); // 15. `List<E> subList(int fromIndex, int toIndex);`:通过指定起始位置以及结束位置裁剪集合 System.out.println("=============================add============================="); // 16. `boolean equals(Object o);`:判断集合是否相同 System.out.println("=============================add============================="); // 17. `Object[] toArray();`:将集合转为数组 System.out.println("=============================add============================="); // 18. `int size();`:返回集合长度(元素数量) System.out.println("=============================size============================="); System.out.println(linkedList.size()); // 19. `void clear();`:清空集合(将所有元素删除) System.out.println("=============================add============================="); // 20. `boolean isEmpty();`:判断集合是否为空(不是null) System.out.println("=============================isEmpty============================="); System.out.println(linkedList.isEmpty()); // 21. `Iterator<E> iterator();`:返回集合可迭代对象 System.out.println("=============================add============================="); // 22. `default Stream<E> stream()`:返回集合的Stream流 System.out.println("=============================add============================="); // 23. `public void addFirst(E e)`:在首部插入元素 System.out.println("=============================addFirst============================="); linkedList.addFirst("向头部插入数据"); // 24. `public void addLast(E e)`:在尾部添加元素 System.out.println("=============================addLast============================="); linkedList.addLast("向尾部添加数据"); System.out.println(linkedList); // 25. `public E getFirst()`:获取第一个节点元素 System.out.println("=============================getFirst============================="); Object first = linkedList.getFirst(); System.out.println(first); // 26. `public E getLast()`:获取最后一个节点元素 System.out.println("=============================getLast============================="); Object last = linkedList.getLast(); System.out.println(last); // 27. `public E removeFirst()`:移除第一个节点元素 System.out.println("=============================removeFirst============================="); Object removeFirst = linkedList.removeFirst(); System.out.println(removeFirst); System.out.println(linkedList); // 28. `public E removeLast()`:移除最后一个节点元素 System.out.println("=============================removeLast============================="); Object removeLast = linkedList.removeLast(); System.out.println(removeLast); System.out.println(linkedList); // 29. `public boolean offerFirst(E e)`:将指定元素插入到列表开头 System.out.println("=============================offerFirst============================="); boolean offerFirst = linkedList.offerFirst("offerFirst"); System.out.println(offerFirst); System.out.println(linkedList); // 30. `public boolean offerLast(E e)`:将指定元素插入到列表结尾 System.out.println("=============================offerLast============================="); boolean offerLast = linkedList.offerLast("offerLast"); System.out.println(offerLast); System.out.println(linkedList); // 31. `public E peekFirst()`:获取首节点元素,但是不删除 System.out.println("=============================peekFirst============================="); Object peekFirst = linkedList.peekFirst(); System.out.println(peekFirst); System.out.println(linkedList); // 32. `public E peekLast()`:获取尾结点元素,但是不删除 System.out.println("=============================peekLast============================="); Object peekLast = linkedList.peekLast(); System.out.println(peekLast); System.out.println(linkedList); // 33. `public E pollFirst()`:获取首节点元素,并删除 System.out.println("=============================pollFirst============================="); Object pollFirst = linkedList.pollFirst(); System.out.println(pollFirst); System.out.println(linkedList); // 34. `public E pollLast()`:获取尾结点元素,并删除 System.out.println("=============================pollLast============================="); Object pollLast = linkedList.pollLast(); System.out.println(pollLast); System.out.println(linkedList); } }5. LinkedList存储方式源码分析
LinkedList的数据存储都是使用的Node节点对象,并且默认存储时指向第一个和最后一个Node节点对象,用于便捷操作
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable { // 集合元素长度 transient int size = 0; // 指向第一个节点的指针。不变量:(first == null && last == null) || (first.prev == null && first.item != null) transient Node<E> first; // 指向最后一个节点的指针。不变量:(first == null && last == null) || (last.next == null && last.item != null) transient Node<E> last; // Node内部类就是LinkedList的存储格式 // Node节点类 private static class Node<E> { // item就是data用于存储数据 E item; // next就是指向下一个节点对象地址 Node<E> next; // prev就是指向上一个节点对象地址 Node<E> prev; // Node节点对象构造方法 Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } } }4. List接口实现类之Vector类(熟悉)
1. Vector概述
Vector与ArrayList是相同的,尤其是用法基本完全一致,唯一的区别在于ArrayList是线程不安全的,而Vector是线程安全 线程安全代表在多线程情况下能够保证数据的安全性,不会因为多线程操作而导致数据的确定性(数据结果与最终想要的结果不一致) 线程安全与线程不安全的体现在于这两个类中的方法修饰,线程安全会多一个关键字
synchronized
线程同步关键字,线程不安全的则没有此关键字修饰 以上就是Vector与ArrayList的区别,其他的方法基本上完全一致线程安全会造成程序的运行效率降低,线程不安全则不会影响效率问题
2. Vector构造方法
// 使用空参构造方法创建对象 public Vector() { // 默认初始化容量为10(10个元素) this(10); } // 使用带参构造方法指定初始容量大小,创建对象 public Vector(int initialCapacity) { this(initialCapacity, 0); } // 使用带参构造方法创建对象,并将其他集合的数据添加至创建的对象内 public Vector(Collection<? extends E> c) { elementData = c.toArray(); elementCount = elementData.length; // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, elementCount, Object[].class); }3. Vector常用方法
boolean add(E e);
:向集合中添加新的元素
void add(int index, E element);
:向集合中指定位置插入元素
boolean addAll(Collection<? extends E> c);
:向集合中添加c集合的所有元素,将c集合中的所有元素添加到此集合中
c:Collection以及子孙类都可以,集合参数
boolean addAll(int index, Collection<? extends E> c);
:向集合中指定位置插入c集合的所有元素
E get(int index);
:获取集合中指定位置的元素
boolean contains(Object o);
:判断集合中是否包含指定元素
boolean containsAll(Collection<?> c);
:判断集合中是否包含指定集合的元素
int indexOf(Object o);
:判断集合中是否存在指定元素(只判断第一次出现的),并返回此元素的下标索引位置,如果没有找到则返回-1
int lastIndexOf(Object o);
:判断集合中是否存在指定元素(只判断最后一次出点的),并返回此元素的下标索引位置,如果没有找到则返回-1
boolean remove(Object o);
:从集合中移除指定元素
E remove(int index);
:通过下标索引删除集合中的元素
boolean removeAll(Collection<?> c);
:从集合中移除c集合的所有相同元素
E set(int index, E element);
:修改指定下标索引的元素
default void sort(Comparator<? super E> c)
:通过比较器给集合排序
List<E> subList(int fromIndex, int toIndex);
:通过指定起始位置以及结束位置裁剪集合
boolean equals(Object o);
:判断集合是否相同
Object[] toArray();
:将集合转为数组
int size();
:返回集合长度(元素数量)
void clear();
:清空集合(将所有元素删除)
boolean isEmpty();
:判断集合是否为空(不是null)
Iterator<E> iterator();
:返回集合可迭代对象
default Stream<E> stream()
:返回集合的Stream流
public synchronized void addElement(E obj)
:向集合中添加元素,不返回任何内容
public synchronized int capacity()
:返回当前集合中的数组长度,注意与size不同,size是返回元素个数
public synchronized E firstElement()
:获取集合中的第一个元素
public synchronized E lastElement()
:获取集合中的最后一个元素
public synchronized boolean removeElement(Object obj)
:移除集合中的指定元素
public synchronized void setSize(int newSize)
:设置集合长度4. Vector代码案例
public class Demo { public static void main(String[] args) { // 创建Vector对象 Vector vector = new Vector(); // 1. `boolean add(E e);`:向集合中添加新的元素 System.out.println("============================add============================"); vector.add("梅超风"); vector.add("何仙姑"); vector.add("张道陵"); vector.add("张友人"); vector.add("张百忍"); vector.add("玉皇大帝"); vector.add(1.23); vector.add(1, "玉皇大帝"); System.out.println(vector); // 5. `E get(int index);`:获取集合中指定位置的元素 System.out.println("============================get============================"); Object o = vector.get(2); System.out.println(o); // 6. `boolean contains(Object o);`:判断集合中是否包含指定元素 System.out.println("============================contains============================"); boolean isContains = vector.contains("张友人"); System.out.println(isContains); // 8. `int indexOf(Object o);`:判断集合中是否存在指定元素(只判断第一次出现的),并返回此元素的下标索引位置,如果没有找到则返回-1 System.out.println("============================indexOf============================"); int indexOf = vector.indexOf("玉皇大帝"); System.out.println(indexOf); // 9. `int lastIndexOf(Object o);`:判断集合中是否存在指定元素(只判断最后一次出点的),并返回此元素的下标索引位置,如果没有找到则返回-1 System.out.println("============================lastIndexOf============================"); int lastIndexOf = vector.lastIndexOf("玉皇大帝"); System.out.println(lastIndexOf); // 10. `boolean remove(Object o);`:从集合中移除指定元素 System.out.println("============================remove============================"); boolean remove = vector.remove(1.23); System.out.println(remove); System.out.println(vector); // 13. `E set(int index, E element);`:修改指定下标索引的元素 System.out.println("============================set============================"); Object oldValue = vector.set(0, "元始天尊"); System.out.println(oldValue); System.out.println(vector); // 17. `Object[] toArray();`:将集合转为数组 System.out.println("============================toArray============================"); Object[] objects = vector.toArray(); System.out.println(Arrays.toString(objects)); // 18. `int size();`:返回集合长度(元素数量) System.out.println("============================size============================"); int size = vector.size(); System.out.println(size); // 19. `void clear();`:清空集合(将所有元素删除) System.out.println("============================isEmpty============================"); System.out.println(vector.isEmpty()); // 23. `public synchronized void addElement(E obj)`:向集合中添加元素,不返回任何内容 System.out.println("============================addElement============================"); vector.addElement("猪刚鬣"); System.out.println(vector); // 24. `public synchronized int capacity()`:返回当前集合中的数组长度,注意与size不同,size是返回元素个数 System.out.println("============================capacity============================"); int capacity = vector.capacity(); System.out.println(capacity); // 25. `public synchronized E firstElement()`:获取集合中的第一个元素 System.out.println("============================firstElement============================"); Object o1 = vector.firstElement(); System.out.println(o1); // 26. `public synchronized E lastElement()`:获取集合中的最后一个元素 System.out.println("============================lastElement============================"); Object o2 = vector.lastElement(); System.out.println(o2); // 27. `public synchronized boolean removeElement(Object obj)`:移除集合中的指定元素 System.out.println("============================removeElement============================"); boolean isRemoveElement = vector.removeElement("猪刚鬣"); System.out.println(isRemoveElement); System.out.println(vector); // 28. `public synchronized void setSize(int newSize)`:设置集合长度 System.out.println("============================setSize============================"); System.out.println("调用setSize前"); System.out.println(vector.size()); System.out.println(vector.capacity()); vector.setSize(50); System.out.println("调用setSize后"); System.out.println(vector.size()); System.out.println(vector.capacity()); } }5. ArrayList/LinkedList/Vector总结(重点看区别)
1. ArrayList/LinkedList/Vector的区别(重点)
ArrayList:底层是基于数组实现(动态数组),增删慢,查询快,线程不安全-->ArrayList常用
数组增删时需要将当前位置之后的数据要么整体向前移,要么整体向后移,所以增加删除速度慢
数组查询速度快原因是可以指定下标索引直接取值
LinkedList:底层是基于双向链表实现,增删快,查询慢,线程不安全
双链表中的节点对象只需要记住他的前一个Node节点以及后一个Node节点,所以增删是不需要移动位置,只需要重新设置指向即可所以增删速度快
双链表查询速度慢是因为不能通过下标索引直接取值,只能从第一个遍历到最后一个节点对象(Java使用了二分查,所以速度相对快一点)
Vector:底层是基于数组实现(动态数组),增删慢,查询快,线程安全
2. ArrayList/LinkedList/Vector的创建对象的方式
由于他们都属于是List接口的直接子类,所以一般创建对象时都是通过多态方式(父类引用指向子类),所以所有的单独方法都无法使用 多态方式创建List集合对象
List list = new ArrayList(); List list = new LinkedList(); List list = new Vector();
3. ArrayList/LinkedList/Vector的统一常用方法(掌握)
boolean add(E e);
:向集合中添加新的元素
boolean addAll(int index, Collection<? extends E> c);
:向集合中指定位置插入c集合的所有元素
E get(int index);
:获取集合中指定位置的元素
int indexOf(Object o);
:判断集合中是否存在指定元素(只判断第一次出现的),并返回此元素的下标索引位置,如果没有找到则返回-1
boolean remove(Object o);
:删除集合中的指定元素
E set(int index, E element);
:修改指定下标索引的元素
int size()
:获取集合中元素的个数
boolean isEmpty()
:判断集合是否为空
boolean contains(Object o)
:判断集合中是否包含指定元素
Iterator<E> iterator()
:获取集合中迭代器对象4. ArrayList/LinkedList/Vector的统一常用方法代码案例
public class Demo { public static void main(String[] args) { // 多态方式创建三个集合对象 List arrayList = new ArrayList(); List linkedList = new LinkedList(); List vector = new Vector(); // 1. `boolean add(E e);`:向集合中添加新的元素 System.out.println("===========================add==========================="); arrayList.add("张百忍"); arrayList.add("玉皇大帝"); arrayList.add("王母娘娘"); arrayList.add("猪刚鬣"); arrayList.add("卷门帘子"); arrayList.add("月老"); System.out.println(arrayList); linkedList.add("张百忍"); linkedList.add("玉皇大帝"); linkedList.add("王母娘娘"); linkedList.add("猪刚鬣"); linkedList.add("卷门帘子"); linkedList.add("月老"); System.out.println(linkedList); vector.add("张百忍"); vector.add("玉皇大帝"); vector.add("王母娘娘"); vector.add("猪刚鬣"); vector.add("卷门帘子"); vector.add("月老"); System.out.println(vector); // 2. `boolean addAll(int index, Collection<? extends E> c);`:向集合中指定位置插入c集合的所有元素 System.out.println("===========================addAll==========================="); // 3. `E get(int index);`:获取集合中指定位置的元素 System.out.println("===========================get==========================="); Object o1 = arrayList.get(1); Object o2 = linkedList.get(1); Object o3 = vector.get(1); System.out.println(o1); System.out.println(o2); System.out.println(o3); // 4. `int indexOf(Object o);`:判断集合中是否存在指定元素(只判断第一次出现的),并返回此元素的下标索引位置,如果没有找到则返回-1 System.out.println("===========================indexOf==========================="); int indexOf1 = arrayList.indexOf("卷门帘子"); int indexOf2 = linkedList.indexOf("卷门帘子"); int indexOf3 = vector.indexOf("卷门帘子"); System.out.println(indexOf1); System.out.println(indexOf2); System.out.println(indexOf3); // 5. `boolean remove(Object o);`:删除集合中的指定元素 System.out.println("===========================remove==========================="); boolean isRemove1 = arrayList.remove("猪刚鬣"); boolean isRemove2 = linkedList.remove("猪刚鬣"); boolean isRemove3 = vector.remove("猪刚鬣"); System.out.println(isRemove1); System.out.println(isRemove2); System.out.println(isRemove3); System.out.println(arrayList); System.out.println(linkedList); System.out.println(vector); // 6. `E set(int index, E element);`:修改指定下标索引的元素 System.out.println("===========================set==========================="); Object oldValue1 = arrayList.set(0, "张友人"); Object oldValue2 = linkedList.set(0, "张友人"); Object oldValue3 = vector.set(0, "张友人"); System.out.println(oldValue1); System.out.println(oldValue2); System.out.println(oldValue3); System.out.println(arrayList); System.out.println(linkedList); System.out.println(vector); // 7. `int size()`:获取集合中元素的个数 System.out.println("===========================size==========================="); int size1 = arrayList.size(); int size2 = linkedList.size(); int size3 = vector.size(); System.out.println(size1); System.out.println(size2); System.out.println(size3); // 8. `boolean isEmpty()`:判断集合是否为空 System.out.println("===========================isEmpty==========================="); boolean empty1 = arrayList.isEmpty(); boolean empty2 = linkedList.isEmpty(); boolean empty3 = vector.isEmpty(); System.out.println(empty1); System.out.println(empty2); System.out.println(empty3); // 9. `boolean contains(Object o)`:判断集合中是否包含指定元素 System.out.println("===========================contains==========================="); boolean isContains1 = arrayList.contains("玉皇大帝"); boolean isContains2 = linkedList.contains("玉皇大帝"); boolean isContains3 = vector.contains("玉皇大帝"); System.out.println(isContains1); System.out.println(isContains2); System.out.println(isContains3); } }3. 泛型(重点)
1. 泛型概述
泛型是在JDK1.5后添加的,泛型用于帮助我们建立更加安全的集合,使用了泛型后不必再进行强制类型转换(也不会出现类型转换异常) JDK提供了支持泛型的编译器,将运行时的类型检查提前到了编译时执行-->泛型,就是用于规范(规定)数据类型,让数据类型统一 使用泛型可以让代码的可读性和安全性更高
2. 集合中的泛型(重点)
定义集合时如果不添加泛型则集合中什么元素都可以添加,泛型在集合中的作用就是用于限制集合中可以添加数据有哪些,限制后则不可以随意添加数据 集合中使用泛型也是确保使用集合的安全性,以及可读性 集合中使用泛型格式:
List<泛型类型> list = new List集合子类<>();
泛型类型:代表集合中可以使用的类型是什么,支持引用数据类型
1. 集合中泛型的使用代码案例
public class Demo { public static void main(String[] args) { // 集合中的泛型定义使用 List<String> list = new ArrayList<>(); // 添加数据 boolean isAdd = list.add("安倍晋三"); System.out.println(isAdd); System.out.println(list); list.add("卒于2022-07-08"); System.out.println(list); // 获取数据 String value = list.get(0); System.out.println(value); // 添加实体类数据 List<People> peopleList = new ArrayList<>(); // 添加数据 peopleList.add(new People("小龙女", "龙", 18)); peopleList.add(new People("杨过", "男", 18)); peopleList.add(new People("白素贞", "母", 18)); peopleList.add(new People("许仙", "男", 18)); System.out.println(peopleList); // 获取数据 People people = peopleList.get(1); System.out.println(people); // 集合中的泛型可以嵌套-->List集合套一个List集合(俄罗斯套娃) List<List<String>> lists = new ArrayList<>(); // 添加数据 // 定义新的List集合用于添加元素 List<String> stringList = new ArrayList<>(); List<Integer> integerList = new ArrayList<>(); // 添加String数据 stringList.add("嬴政"); stringList.add("焊武帝"); stringList.add("刘邦"); stringList.add("项羽"); // 添加Integer集合数据 integerList.add(1); integerList.add(2); integerList.add(3); integerList.add(4); // 向List集合中添加List集合数据 lists.add(stringList); lists.add(stringList); lists.add(stringList); lists.add(stringList); // 输出结果 System.out.println(lists); } }以上是集合中使用泛型的案例,但是一般很少会出现嵌套List形式,并且就算是嵌套也不能超过2层
3. 泛型擦除补偿
Java的运行分为两个部分,
编译
和运行
两个部分,泛型的出现是提高了编译期
的安全性,由于在编译期已经确定了类型,那么运行时则不会重新检查(不检测数据的类型) 泛型擦除则是在运行期间体现,一旦运行后则将泛型擦除(原本定义的泛型全部失效),所有的类型都为Object
,这个过程就是泛型擦除补偿
泛型在编译期用于确保程序的安全性,但是在运行期则会将泛型去除(擦除),重新更改为Object
类型4. 泛型的定义以及使用(重点)
1. 泛型的定义概述
上面学完了集合中使用泛型,但是我们还不到如何定义泛型,泛型定义时的注意事项有哪些,泛型支持自定义(自己创建的类也可以使用泛型类型) 泛型可以在类,方法,接口,属性中使用
2. 泛型定义的格式
1. 泛型在类上定义格式
泛型在类上定义
修饰符 class 类名<定义泛型类型变量>{ // 类的属性方法等 }代码案例
/** * 定义泛型类 * * @param <T> T-->type,泛型的类型,代表定义泛型变量 * String name-->定义了字符串变量 */ public class GenericsClass<T> { // 属性中使用泛型类型 private T t; public GenericsClass() { } // 形参使用泛型类型 public GenericsClass(T t) { this.t = t; } // 返回值使用泛型类型 public T getT() { return t; } public void setT(T t) { this.t = t; } }测试类
public class Demo { public static void main(String[] args) { // 创建自定义的泛型类 // 一下两个相同 // GenericsClass genericsClass = new GenericsClass(); // List list = new ArrayList<>(); // 创建自定义泛型类,指定泛型类型为String GenericsClass<String> genericsClass1 = new GenericsClass<>(); // 创建自定义泛型类,指定泛型类型为Integer GenericsClass<Integer> genericsClass2 = new GenericsClass<>(); // 设置数据 // 由于使用了泛型类型,所以只能设置String类型数据 genericsClass1.setT("彭于晏"); // 由于使用了泛型类型,所以只能设置Integer类型数据 genericsClass2.setT(185); } }以上是定义泛型类以及使用的过程
注意:带有尖括号(<>)则代表是定义泛型类型变量,不带尖括号(<>)则代表是使用泛型变量
2. 泛型在方法上定义
泛型在方法中定义方式
修饰符 <定义泛型变量> 返回值类型 (形参列表){ // 方法体 }泛型方法的定义
public class GenericsMethod { /** * 在方法中定义泛型类型 * * @param t 形参为泛型类型参数(传入的参数是什么就是什么类型) * @param <T> 定义泛型变量 */ public static <T> void method01(T t) { // 输出传入的参数以及参数类型 System.out.println("传入的参数为:" + t); // getClass()方法用于获取数据的类型(当前类的类型) System.out.println("参数类型为:" + t.getClass()); } /** * 方法中定义泛型类型并使用 * * @param t 形参为泛型类型参数(传入的参数是什么就是什么类型) * @param <T> 定义泛型变量 * @return 返回值也是泛型类型 */ public static <E> E method02(E t) { // 输出传入的参数以及参数类型 System.out.println("传入的参数为:" + t); // getClass()方法用于获取数据的类型(当前类的类型) System.out.println("参数类型为:" + t.getClass()); // 泛型类型返回值不是代表可以随意返回任意类型,而是必须返回的类型与泛型变量相同 // 说到底就是只能返回泛型类型的返回值 return t; } }测试类
public class Demo { public static void main(String[] args) { // 使用方法中定义的泛型 // 当传入字符串类型时方法的泛型类型就被确认了 GenericsMethod.method01("彭于晏"); // 当传入字符串类型时方法的泛型类型就被确认了,所以返回值直接返回的就是String类型 String resultValue = GenericsMethod.method02("彭于晏"); // 输出结果 System.out.println(resultValue); } }3. 接口中定义泛型类型
接口中定义泛型类型时在实现接口时,类上也可以定义泛型,并且可以与接口的泛型通用(可以将类上定义的泛型变量当做参数传给接口),也可以在实现时定义接口的泛型类型 使用方式1 接口定义
/** * 泛型接口 * * @param <T> 定义泛型变量 */ public interface GenericsInterface<T> { /** * 泛型方法 * * @param t 使用接口中定义的泛型变量当做形参 */ void func(T t); }实现类定义
/** * 实现泛型接口时可以指定泛型类型,指定后重写的方法也会是相同类型 */ public class ImplementsClass01 implements GenericsInterface<String> { /** * 重写泛型接口方法 * * @param s 形参列表,类型为使用泛型接口时定义的String类型 */ @Override public void func(String s) { System.out.println("传入的类型为:" + s.getClass()); System.out.println("参数为:" + s); } }测试类
public class Demo { public static void main(String[] args) { // 泛型接口实现类1 ImplementsClass01 implementsClass01 = new ImplementsClass01(); // 调用方法 implementsClass01.func("传入参数"); } }使用方式2 接口定义
/** * 泛型接口 * * @param <T> 定义泛型变量 */ public interface GenericsInterface<T> { /** * 泛型方法 * * @param t 使用接口中定义的泛型变量当做形参 */ void func(T t); }实现类定义
/** * 自定义类实现泛型接口时不指定泛型类型,而是定义一个泛型变量,将泛型变量当做参数传给接口 * * @param <T> 定义泛型变量 */ public class ImplementsClass02<T> implements GenericsInterface<T> { /** * 重写泛型接口方法 * * @param t 使用接口中定义的泛型变量当做形参 */ @Override public void func(T t) { System.out.println("传入的类型为:" + t.getClass()); System.out.println("参数为:" + t); } }测试类
public class Demo { public static void main(String[] args) { // 泛型接口实现类2 ImplementsClass02<Integer> implementsClass02 = new ImplementsClass02<>(); // 调用方法 implementsClass02.func(123); } }5. 泛型通配符(熟悉)
1. 泛型通配符概述
泛型是用于限定数据类型,当集合或自定义类中使用泛型时可以明确泛型的数据类型,那么使用时只能传输给定的数据类型,否则会出现错误 在实际开发中可能会出现在定义方法时,根本无法确定具体的数据类型是什么,为了解决这个
不确定性
泛型提供了通配符供我们使用2. 泛型通配符分类
1. 无限定通配符:
<?>
-->任意泛型类型都可以2. 上限通配符:
<? extends 泛型类型>
-->只允许泛型类型及其子孙类如果泛型类型为:String类型,参数则必须是String类型或者其子孙类型
3. 下限通配符:
<? supper 泛型类型>
-->只允许泛型类型及其父类如果泛型类型为:String类型,参数则必须是String类型或者其父类
3. 泛型通配符代码案例
创建类的父子关系
爷爷类
public class YeClass { }父亲类
/** * 父类继承爷爷类 */ public class FuClass extends YeClass { }子孙类
/** * 子类继承父类 */ public class ZiClass extends FuClass{ }1. 无限定通配符
public class Demo { public static void main(String[] args) { // 定义集合类型 List<String> list1 = new ArrayList<>(); List<Integer> list2 = new ArrayList<>(); List<ZiClass> list3 = new ArrayList<>(); // 调用方法,func00的方法参数为List<String>类型,已经写死必须只能传入此类型,其他类型则不行 func00(list1); // 传入其他List集合类型 // func00(list2); // 使用无限定通配符传入参数,允许任意List集合的参数类型 func01(list1); func01(list2); func01(list3); } /** * 限定泛型类型方法 * * @param list 形参 */ public static void func00(List<String> list) { System.out.println(list); } /** * 无限定泛型类型方法 * * @param list 形参 */ public static void func01(List<?> list) { System.out.println(list); } }2. 上限通配符
public class Demo { public static void main(String[] args) { // 调用上限通配符方法 // 定义集合 // 祖宗类 List<YeClass> yeClasses = new ArrayList<>(); // 父类 List<FuClass> fuClasses = new ArrayList<>(); // 子孙类 List<ZiClass> ziClasses = new ArrayList<>(); // 传入祖宗类,不允许 // func02(yeClasses); // 传入父类允许 func02(fuClasses); // 传入子类允许 func02(ziClasses); } /** * 上限通配符,只支持FuClass及其子孙类 * * @param list 形参 */ public static void func02(List<? extends FuClass> list) { System.out.println(list); } }3. 下限通配符
public class Demo { public static void main(String[] args) { // 创建集合对象 // 祖宗类 List<YeClass> yeClasses = new ArrayList<>(); // 父类 List<FuClass> fuClasses = new ArrayList<>(); // 子孙类 List<ZiClass> ziClasses = new ArrayList<>(); // 调用下限通配符方法 // 传入父类允许 func03(yeClasses); // 传入本类允许 func03(fuClasses); // 传入子孙类不允许 // func03(ziClasses); } /** * 下限通配符,只支持FuClass及其父类 * * @param list 形参 */ public static void func03(List<? super FuClass> list) { System.out.println(list); } }4. 迭代器(掌握)
1. Iterator迭代器
1. Iterator概述
Iterator迭代器一般用于集合迭代,迭代器中存储的是集合元素,与集合类似,都会存储数据,但是存储的方式不同,一般只要取出集合元素通过通用方式遍历都会用到迭代器 Iterator迭代器是一种集合通用遍历方式,这样针对Collection集合的遍历更加简单更加统一,并且能达到逻辑代码与具体实现相分类的效果(解耦效果) Collection集合中通用的获取方式都是使用
Iterator<E> iterator()
方法获取,通用获取方式,但是每个集合中也会有自己独立的获取,但是一般只要使用多态方式获取基本用统一的获取方式即可2. Iterator集合获取方式
Collection集合通用获取方式,调用集合的
Iterator<E> iterator()
方法获取 例如:// 定义集合类型 List<泛型类型> list = new 集合实现类(); // 获取Iterator迭代器方法 Iterator iterator = list.iterator();3. Iterator常用方法
boolean hasNext()
:用于判断迭代器中是否有下一个元素
E next()
:指向迭代器中的下一个元素,每次调用next都会记录当前指向的位置
default void remove()
:从迭代器中移除一个next指向的元素,如果next的指向不是元素则会报异常4. Iterator代码案例
public class Demo { public static void main(String[] args) { // 定义集合 List<String> list = new ArrayList<>(); // 添加数据 list.add("梅超风"); list.add("秦始皇"); list.add("基尼太美"); list.add("裘千尺"); // 输出结果 System.out.println(list); // 获取迭代器,通过调用iterator方法,返回迭代器对象 Iterator<String> iterator = list.iterator(); // 调用迭代器方法 // 1. `boolean hasNext()`:用于判断迭代器中是否有下一个元素 System.out.println("============================hasNext============================"); boolean hasNext = iterator.hasNext(); System.out.println(hasNext); // 2. `E next()`:指向迭代器中的下一个元素 System.out.println("============================next============================"); // 当next指向下一个元素时会将元素返回 /*String next = iterator.next(); System.out.println(next); hasNext = iterator.hasNext(); System.out.println(hasNext); next = iterator.next(); System.out.println(next); hasNext = iterator.hasNext(); System.out.println(hasNext); next = iterator.next(); System.out.println(next); hasNext = iterator.hasNext(); System.out.println(hasNext); next = iterator.next(); System.out.println(next); hasNext = iterator.hasNext(); System.out.println(hasNext); next = iterator.next(); System.out.println(next);*/ // 使用hasNext与next结合的方式遍历Iterator迭代器数据 while (iterator.hasNext()) { // 在循环内调用next方法,用于指向下一个元素 String next = iterator.next(); // 判断当前数据是否为基尼太美,如果是则删除 if ("基尼太美".equals(next)) { // 移除迭代器元素 iterator.remove(); } System.out.println(next); } // 打印List集合数据,List集合中的数据也被移除了,Iterator迭代的就是List的数据 System.out.println(list); // 3. `default void remove()`:从迭代器中移除一个元素 System.out.println("============================remove============================"); } }Iterator迭代器用于遍历集合中的数据,并且所有操作与List集合都有关联,例如Iterator迭代器的移除方法,移除后List集合的数据也会被移除
2. ListIterator迭代器(了解熟悉)
1. ListIterator概述
ListIterator是Iterator的子接口,但是比Iterator更加强大(多了一些方法),提供的这些方法让ListIterator使用起来更加方便
2. ListIterator获取方式
通过List集合方法获取:
// 定义集合 List<泛型类型> list = new 集合类型<>(); // 获取ListIterator迭代器 ListIterator<泛型类型> listIterator = list.listIterator();3. ListIterator常用方法
boolean hasNext()
:用于判断迭代器中是否有下一个元素
E next()
:指向迭代器中的下一个元素,每次调用next都会记录当前指向的位置
default void remove()
:从迭代器中移除一个next指向的元素,如果next的指向不是元素则会报异常
boolean hasPrevious()
:用于逆向遍历集合,判断迭代器前面是否存在元素
E previous()
:指向迭代器中的前一个元素,每次调用previous都会记录当前指向的位置
void set(E e)
:从迭代器中将指定的next或previous返回的元素更改为指定元素
void add(E e)
:将指定元素插入之集合中,插入位置是当前迭代器迭代的位置之前4. ListIterator代码案例
public class Demo { public static void main(String[] args) { // 定义集合 List<String> list = new ArrayList<>(); // 添加数据 list.add("梅超风"); list.add("秦始皇"); list.add("基尼太美"); list.add("裘千尺"); list.add("安倍晋三"); // 输出结果 System.out.println(list); // 获取ListIterator迭代器 ListIterator<String> listIterator = list.listIterator(); // 1. `boolean hasNext()`:用于判断迭代器中是否有下一个元素 // 2. `E next()`:指向迭代器中的下一个元素,每次调用next都会记录当前指向的位置 /*while (listIterator.hasNext()) { // 调用next方法返回元素 String next = listIterator.next(); System.out.println(next); }*/ System.out.println("========================="); // 3. `default void remove()`:从迭代器中移除一个next指向的元素,如果next的指向不是元素则会报异常 // 4. `boolean hasPrevious()`:用于逆向遍历集合,判断迭代器前面是否存在元素 // 5. `E previous()`:指向迭代器中的前一个元素,每次调用previous都会记录当前指向的位置 /*while (listIterator.hasPrevious()) { // 调用previous方法返回元素 String previous = listIterator.previous(); System.out.println(previous); }*/ /*while (true) { while (listIterator.hasNext()) { // 调用next方法返回元素 String next = listIterator.next(); System.out.println(next); } while (listIterator.hasPrevious()) { // 调用previous方法返回元素 String previous = listIterator.previous(); System.out.println(previous); } }*/ // 6. `void set(E e)`:从迭代器中将指定的next或previous返回的元素更改为指定元素 // listIterator.next(); // listIterator.set("石榴姐"); // System.out.println(list); // 7. `void add(E e)`:将指定元素插入之集合中,插入位置是当前迭代器迭代的位置之前 listIterator.add("石榴姐"); System.out.println(list); } }5. Map接口(重点)
1. Map接口概述
现实生活中我们经常存储一些信息例如身份证:身份证号对应姓名,微信:一个手机号对应一个微信号,夫妻:一夫一妻 Map集合的存储方式就是一一对应的方式-->
key
=value
-->键
对应值
-->键值对
例如:身份证号与姓名的对应-->key=身份证号,value=姓名 Map集合中的key不允许重复,value允许重复 语法格式:key=value
2. Map接口常用方法
V put(K key, V value)
:向Map集合中添加元素(键值对元素),如果添加的可以是重复的则会覆盖value值(key不覆盖)
V get(Object key)
:通过指定key获取value值
default V getOrDefault(Object key, V defaultValue)
:通过key获取value值,如果此key不存在则使用默认值输出
V remove(Object key)
:通过指定key移除key和value
boolean containsKey(Object key)
:判断Map集合中是否包含指定key
boolean containsValue(Object value)
:判断集合中是否包含指定value
Collection<V> values()
:返回Map集合中的所有value值
Set<K> keySet()
:返回Map集合中的所有key值
Set<Map.Entry<K, V>> entrySet()
:返回Map集合中的所有key-value值(返回所有键值对)
int size()
:返回Map集合中的key-value数量
void clear()
:清空Map集合所有元素
boolean isEmpty()
:判断Map集合是否为空3. Map接口实现类
1. Map接口之实现类概述
由于Map属于接口,所以无法直接创建对象,只能通过其子孙类创建对象,子孙类中只需要知道4个类即可,并且实现类实现了Map接口的方法,并且方法基本通用
2. Map接口之HashMap实现类(重点)
1. HashMap类概述(理解)
HashMap底层是采用哈希算法实现,是Map接口最常用的实现类,由于底层采用哈希算法所以它存储方式要求不允许出现重复的数据,哈希算法又被称之为
哈希表
,所以可以称HashMap底层由哈希表组成,但是注意,JDK1.8后HashMap集合底层除了哈希表之外还会使用红黑树作为数据存储注意:JDK1.8中的HashMap集合在存储数据长度为8之前采用哈希表存储,长度超过8时改为红黑树存储
哈希表的组成:链表
+数组
-->解决了数组和链表的共性问题,哈希表的速度会提升很大 HashMap的底层使用的数据类型比较多,且会解决很大的效率问题2. HashMap构造方法
// 使用空参构造方法创建HashMap对象 public HashMap() { // 创建HashMap对象时赋值默认长度 this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted } // 创建HashMap对象并指定初始化容量 public HashMap(int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR); } // 创建HashMap对象并指定Map集合数据,添加至Map集合 public HashMap(Map<? extends K, ? extends V> m) { this.loadFactor = DEFAULT_LOAD_FACTOR; putMapEntries(m, false); }3. HashMap常用方法
V put(K key, V value)
:向Map集合中添加元素(键值对元素),如果添加的可以是重复的则会覆盖value值(key不覆盖)
V get(Object key)
:通过指定key获取value值
default V getOrDefault(Object key, V defaultValue)
:通过key获取value值,如果此key不存在则使用默认值输出
V remove(Object key)
:通过指定key移除key和value
boolean containsKey(Object key)
:判断Map集合中是否包含指定key
boolean containsValue(Object value)
:判断集合中是否包含指定value
Collection<V> values()
:返回Map集合中的所有value值
Set<K> keySet()
:返回Map集合中的所有key值
Set<Map.Entry<K, V>> entrySet()
:返回Map集合中的所有key-value值(返回所有键值对)
返回值为Set集合,Set集合中有一个Entry接口,其中包含了获取Key和Value的方法
K getKey()
:获取Entry中的key值
V getValue()
:获取Entry中的value值
int size()
:返回Map集合中的key-value数量
void clear()
:清空Map集合所有元素
boolean isEmpty()
:判断Map集合是否为空4. HashMap代码案例
public class Demo { public static void main(String[] args) { // 创建HashMap集合对象 HashMap<String, String> idCard = new HashMap<>(); // 设置数据 // 1. `V put(K key, V value)`:向Map集合中添加元素(键值对元素),如果添加的可以是重复的则会覆盖value值(key不覆盖) System.out.println("====================put===================="); idCard.put("20021230", "彭于晏"); idCard.put("20021231", "鞠婧祎"); idCard.put("15000203", "天山童姥"); idCard.put("10000203", "弼马温"); idCard.put("16000509", "黑山老妖"); idCard.put("14000909", "鲲"); System.out.println(idCard); idCard.put("14000909", "基尼太美"); System.out.println(idCard); // 2. `V get(Object key)`:通过指定key获取value值 System.out.println("====================get===================="); String value = idCard.get("基尼太美"); System.out.println(value); value = idCard.get("14000909"); System.out.println(value); // 3. `default V getOrDefault(Object key, V defaultValue)`:通过key获取value值,如果此key不存在则使用默认值输出 System.out.println("====================getOrDefault===================="); String valueDefault = idCard.getOrDefault("基尼太美", "暂无数据"); System.out.println(valueDefault); // 4. `V remove(Object key)`:通过指定key移除key和value System.out.println("====================remove===================="); String removeValue = idCard.remove("10000203"); System.out.println(removeValue); System.out.println(idCard); // 5. `boolean containsKey(Object key)`:判断Map集合中是否包含指定key System.out.println("====================containsKey===================="); boolean containsKey = idCard.containsKey("14000909"); System.out.println(containsKey); containsKey = idCard.containsKey("140009091"); System.out.println(containsKey); // 6. `boolean containsValue(Object value)`:判断集合中是否包含指定value System.out.println("====================containsValue===================="); boolean containsValue = idCard.containsValue("基尼太美"); System.out.println(containsValue); containsValue = idCard.containsValue("基尼太美1"); System.out.println(containsValue); // 7. `Collection<V> values()`:返回Map集合中的所有value值 System.out.println("====================values===================="); Collection<String> values = idCard.values(); System.out.println(values); // 8. `Set<K> keySet()`:返回Map集合中的所有key值 System.out.println("====================keySet===================="); Set<String> keySet = idCard.keySet(); System.out.println(keySet); // 获取Set集合迭代器 Iterator<String> iterator = keySet.iterator(); // 使用while循环输出Iterator迭代器数据 while (iterator.hasNext()) { // 指向迭代器下一条记录并返回结果 String key = iterator.next(); System.out.println(key + ":" + idCard.get(key)); } // 9. `Set<Map.Entry<K, V>> entrySet()`:返回Map集合中的所有key-value值(返回所有键值对) System.out.println("====================entrySet===================="); Set<Map.Entry<String, String>> entries = idCard.entrySet(); Iterator<Map.Entry<String, String>> iterator1 = entries.iterator(); // while循环遍历迭代器 while (iterator1.hasNext()) { Map.Entry<String, String> entry = iterator1.next(); // Entry中的getKey和getValue方法用于获取键和值 System.out.println(entry.getKey() + ":" + entry.getValue()); } // 10. `int size()`:返回Map集合中的key-value数量 System.out.println("====================size===================="); int size = idCard.size(); System.out.println(size); // 11. `void clear()`:清空Map集合所有元素 System.out.println("====================clear===================="); idCard.clear(); // 12. `boolean isEmpty()`:判断Map集合是否为空 System.out.println("====================isEmpty===================="); boolean empty = idCard.isEmpty(); System.out.println(empty); // 添加数据 idCard.put("20200709", "添加数据"); empty = idCard.isEmpty(); System.out.println(empty); } }3. HashMap的put方法源码分析(了解)
// -->HashMap底层存储数据的格式,代表哈希表结构 transient Node<K,V>[] table; // putVal方法,设置值方法 final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { // 数组类型Node节点-->哈希表 Node<K,V>[] tab; // Node节点-->链表结构 Node<K,V> p; // int整数型数据 int n; int i; // (tab = table)将HhashMap的数据临时赋值给tab // (tab = table) == null-->再次验证tab是否等于null // (n = tab.length)将tab的length值赋值给变量n // (n = tab.length) == 0)-->再次验证长度是否为0 if ((tab = table) == null || (n = tab.length) == 0) // 如果length长度为0则代表HashMap创建时为初始化容量,并且是没有数据的 // 将原本的长度重新计算并重新赋值给变量n // resize()如果为null或为0运算的结果过为16-->数组的长度为16 // tab = resize()-->等同于给tab临时变量重新赋值,并且初始化数组的长度为16 n = (tab = resize()).length; // [i = (n - 1) & hash]-->最终的结果为n-1=16-1-->15,15 & hash-->等同于hash 取余 16 // (p = tab[i = (n - 1) & hash])-->将tab临时HashMap的小表索引的数据取出,赋值给p临时变量 // (p = tab[i = (n - 1) & hash]) == null-->如果p==null则代表此下标索引内没有数据 if ((p = tab[i = (n - 1) & hash]) == null) // tab[i]-->i是上方运算出来的结果,当前小标索引的元素 // newNode(hash, key, value, null);-->新建一个Node节点对象,并赋值给tab[i]下标索引 // 小表索引数据为空时首次添加的逻辑 tab[i] = newNode(hash, key, value, null); else { // 声明Node节点对象-->e Node<K,V> e; // 声明泛型变量K-->key K k; // p.hash == hash-->key值的hash计算结果,当前key与当前下标索引的key如果结果相同,则继续验证 // 如果不同则走到else if // ((k = p.key) == key || (key != null && key.equals(k))) // (k = p.key) == key-->判断传入的key是否与上面取出的Node节点的key相同,如果相同则代表是同一个数据 // 如果不同则继续验证 // (key != null && key.equals(k))-->如果==验证为false则验证其内容是否相同,如果相同则进入if // 如果不同则执行else if if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) // 如果相同则将当前下标索引的p节点赋值给e节点 e = p; // 判断取出的临时节点p是否是红黑树类型 else if (p instanceof TreeNode) // 如果是红黑树则通过红黑树的判断验证赋值或覆盖value值 e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); else { // 死循环 for (int binCount = 0; ; ++binCount) { // (e = p.next) == null-->用于取出p节点的下一个指向的节点是否为null // 如果为null则直接赋值,如果不为空则继续循环 if ((e = p.next) == null) { // 将我们新加入的数据添加到next的指向 p.next = newNode(hash, key, value, null); // static final int TREEIFY_THRESHOLD = 8; // binCount >= TREEIFY_THRESHOLD - 1-->用于验证存储的数据是否超过或等于8个 if (binCount >= TREEIFY_THRESHOLD - 1) // 8-1=7 // 将哈希表转为红黑树 treeifyBin(tab, hash); // 跳出循环 break; } // e.hash == hash-->key值的hash计算结果,当前key与当前下标索引的key如果结果相同,则继续验证 // 如果不同则走到else if // ((k = e.key) == key || (key != null && key.equals(k))) // (k = p.key) == key-->判断传入的key是否与上面取出的Node节点的key相同,如果相同则代表是同一个数据 // 如果不同则继续验证 // (key != null && key.equals(k))-->如果==验证为false则验证其内容是否相同,如果相同则进入if // 如果不同则执行else if if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) // 跳出循环-->重新覆盖value值 break; // 将临时Node节点e重新赋值给临时Node节点p变量 p = e; } } // (e != null)将e的node节点判断是否为空,如果不等于null则进入 if (e != null) { // existing mapping for key // 将e临时节点变量中的值取出赋值给oldValue V oldValue = e.value; // onlyIfAbsent-->HashMap集合的put方法传入的始终都是false,取反后始终都是true if (!onlyIfAbsent || oldValue == null) // 将传入的value值赋值给当前e临时节点的value值 e.value = value; // 将新修改的value值的Node节点重新赋值到table中 afterNodeAccess(e); // 返回覆盖前的老值(oldValue return oldValue; } } // 修改的次数 ++modCount; if (++size > threshold) resize(); afterNodeInsertion(evict); return null; }// HashMap的put方法中的hash方法的算法,以及取出数组元素的算法 public class Demo { public static void main(String[] args) { /*String str = "abc"; Object obj = str; // 调用hashCode方法计算hashCode值 int hashCode = obj.hashCode(); System.out.println(hashCode); // (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); int i = hashCode ^ (hashCode >>> 16); System.out.println(hashCode >>> 16); System.out.println(Integer.toBinaryString(hashCode)); System.out.println(Integer.toBinaryString(i)); System.out.println(Integer.toBinaryString(hashCode >>> 16)); // ^异或的二进制运算格式 // 10111100001100010-->96354 // 10111100001100001-->96353 // 00000000000000001 System.out.println(96354 ^ 96353); // 10111100001100010-->96354 // 10111100001100001-->96353 // 00000000000000011*/ String str = "abc"; Object obj = str; // hash值运算结果(key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); // obj.hashCode等同于上面的这个运算key.hashCode() int hashCode = obj.hashCode(); // 使用hashCode>>>16计算结果 int i = hashCode >>> 16; System.out.println(hashCode + "----" + i); int hash = hashCode ^ i; System.out.println(hashCode + "^" + i + "=" + hash); System.out.println(str + "的hash值为:" + hash); // (n - 1) & hash-->算法结果 // (n - 1)=15 // 15 & hash-->值等同于取余16 System.out.println(15 & hash); System.out.println(15 & 654184158); System.out.println(15 & 33); } }4. 二叉树和红黑树二叉树(了解)
二叉树是一种算法,通过算法得出结果,并且也是一种重要的数据类型-->基于底层数据类型
1. 二叉树的定义
二叉树是一种树形结构的类型,需要实际的问题抽象出来的数据结果往往都是二叉树的形式,即使是一半的树也能够简单的转换为二叉树,二叉树是基于链表结构,二叉树的存储结构以及算法较为简单(针对科学家)所以二叉树就显得特别重要 二叉树数据结构的形状是由一个节点以及两颗互不相交的树组成,分别成这两棵树为左子树和右子树,二叉树的树形结构分为五种样式
树形结构样式
第一种:空树,没有数据 第二种:仅有一个节点的二叉树 第三种:仅有左子树的二叉树 第四种:仅有右子树的二叉树 第五种:完整二叉树,带有左子树以及右子树 以上是二叉树的五种基本形态解释以及图解2. 普通二叉树数据排列方式
左子树上的所有节点都比根节点小,右子树的所有节点都比根节点大 例如有这么一组数据:[15,12,14,23,5,16,13,18,4] 运算结果为
以上是二叉树的算法,基本排序,那么问题来了,如果数据是递增或递减,那么将有二叉树变为普通的链表结构3. 平衡二叉树
为了避免二叉树出现的数据一边倒的情况,科学家提出了
平衡二叉树
理论 平衡二叉树中任何节点的两个子树的高度最大差别为1,一旦超出平衡高度则重新运算(重新评估整个二叉树的平衡) 例如最终结果不管是递增还是递减,其数据始终都会保持平衡 保持平衡的原因是由平衡二叉树中平衡因子(-1 0 1),使用平衡引子进行运算,运算后如果当前树一遍倾倒后会重新排列 排列方式就是通过左旋右旋方式,如果偏差向右则向左旋转,如果偏差向左则向右旋转 但是旋转时的次数未知-->需要根据数据量来计算统计(算法统计) 平衡二叉树出现的问题就是每次的缺失平衡后,他的旋转次数(排列次数)是未知的,会造成效率低的问题 例如有这么一组数据:[1,2,3,4,5,6,7,8,9]
以上是平衡二叉树排列的数据 平衡二叉树同样存在问题,数据量大时重新计算排列的次数不确定(不明确),有可能出现排列次数过多情况,影响效率4. 红黑树
为了避免平衡二叉树出现的排列次数不明确的情况,科学家提出了
红黑二叉树
的理论 红黑树是有红色和黑色组成,且只有红和黑,同样黑红数也是一颗自平衡排序二叉树
红黑树的特征特征1. 结点是红色或黑色。 特征2. 根结点是黑色,且永远都是黑色。 特征3. 所有叶子都是黑色。(叶子是null结点) 特征4. 每个红色结点的两个子结点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色结点) 特征5. 从任一结点到其每个叶子的所有路径都包含相同数量的黑色结点。 红黑树通过这些特征从根部延伸知道不平衡时重新计算,并且计算时会知道旋转次数 红黑树的基本操作
插入,2. 删除,3. 左旋,4. 右旋,5. 着色,每插入一条数据或删除一条数据,都可能会导致树的不平衡,从而自动进行
左旋,右旋,着色
操作,使红黑树平衡 红黑树演示网址:https://www.cs.usfca.edu/~galles/visualization/RedBlack.html
例如有这么一组数据:[15,2,3,51,5,65,4,8,15,6,31,54,48,41,23]
5. Map接口之LinkedHashMap实现类(熟悉)
1. LinkedHashMap概述
LinkedHashMap是HashMap的集合的子集合,但是不再是单纯的哈希表组成,而是采用
哈希表+链表
结构,能够保证元素有序(存储顺序与取出顺序相同) LinkedHashMap类和HashMap类用法基本完全相同,LinkedHashMap集合中的Key也不允许重复,存储时允许为null,key也允许为null但是只能存在一个,如果出现key重复则覆盖value值2. LinkedHashMap构造方法
// 空参构造方法,用于创建LinkedHashMap集合对象 public LinkedHashMap() { // 调用父类构造方法 super(); accessOrder = false; } // 创建LinkedHashMap对象并指定初始容量 public LinkedHashMap(int initialCapacity) { super(initialCapacity); accessOrder = false; } // 指定Map集合创建LinkedHashMap集合对象 public LinkedHashMap(Map<? extends K, ? extends V> m) { super(); accessOrder = false; putMapEntries(m, false); }3. LinkedHashMap常用方法
V put(K key, V value)
:向Map集合中添加元素(键值对元素),如果添加的可以是重复的则会覆盖value值(key不覆盖)
V get(Object key)
:通过指定key获取value值
default V getOrDefault(Object key, V defaultValue)
:通过key获取value值,如果此key不存在则使用默认值输出
V remove(Object key)
:通过指定key移除key和value
boolean containsKey(Object key)
:判断Map集合中是否包含指定key
boolean containsValue(Object value)
:判断集合中是否包含指定value
Collection<V> values()
:返回Map集合中的所有value值
Set<K> keySet()
:返回Map集合中的所有key值
Set<Map.Entry<K, V>> entrySet()
:返回Map集合中的所有key-value值(返回所有键值对)
返回值为Set集合,Set集合中有一个Entry接口,其中包含了获取Key和Value的方法
K getKey()
:获取Entry中的key值
V getValue()
:获取Entry中的value值
int size()
:返回Map集合中的key-value数量
void clear()
:清空Map集合所有元素
boolean isEmpty()
:判断Map集合是否为空4. LinkedHashMap代码案例
public class Demo { public static void main(String[] args) { // 创建LinkedHashMap对象 LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>(); // 1. `V put(K key, V value)`:向Map集合中添加元素(键值对元素),如果添加的可以是重复的则会覆盖value值(key不覆盖) System.out.println("======================put======================"); linkedHashMap.put("chi", "小赤"); linkedHashMap.put("cheng", "小橙"); linkedHashMap.put("huang", "小黄"); linkedHashMap.put("lv", "小绿"); linkedHashMap.put("qing", "小青"); linkedHashMap.put("lan", "小蓝"); linkedHashMap.put("zi", "小紫"); linkedHashMap.put("jishi", "鸡屎黄"); linkedHashMap.put("yashi", "鸭屎绿"); // 输出结果 System.out.println(linkedHashMap); // 2. `V get(Object key)`:通过指定key获取value值 System.out.println("======================get======================"); String lv = linkedHashMap.get("lv"); System.out.println(lv); lv = linkedHashMap.get("lv1"); System.out.println(lv); // 3. `default V getOrDefault(Object key, V defaultValue)`:通过key获取value值,如果此key不存在则使用默认值输出 System.out.println("======================getOrDefault======================"); lv = linkedHashMap.getOrDefault("lv", "暂无数据"); System.out.println(lv); lv = linkedHashMap.getOrDefault("lv1", "暂无数据"); System.out.println(lv); // 4. `V remove(Object key)`:通过指定key移除key和value System.out.println("======================remove======================"); String jishi = linkedHashMap.remove("jishi"); System.out.println(jishi); jishi = linkedHashMap.remove("jishi"); System.out.println(jishi); System.out.println(linkedHashMap); // 5. `boolean containsKey(Object key)`:判断Map集合中是否包含指定key System.out.println("======================containsKey======================"); boolean cheng = linkedHashMap.containsKey("cheng"); System.out.println(cheng); cheng = linkedHashMap.containsKey("cheng1"); System.out.println(cheng); // 6. `boolean containsValue(Object value)`:判断集合中是否包含指定value System.out.println("======================containsValue======================"); cheng = linkedHashMap.containsValue("鸭屎绿"); System.out.println(cheng); cheng = linkedHashMap.containsValue("cheng1"); System.out.println(cheng); // 7. `Collection<V> values()`:返回Map集合中的所有value值 System.out.println("======================values======================"); Collection<String> values = linkedHashMap.values(); System.out.println(values); // 8. `Set<K> keySet()`:返回Map集合中的所有key值 System.out.println("======================keySet======================"); Set<String> keySet = linkedHashMap.keySet(); System.out.println(keySet); // 9. `Set<Map.Entry<K, V>> entrySet()`:返回Map集合中的所有key-value值(返回所有键值对) // 1. 返回值为Set集合,Set集合中有一个Entry接口,其中包含了获取Key和Value的方法 // 1. `K getKey()`:获取Entry中的key值 // 2. `V getValue()`:获取Entry中的value值 System.out.println("======================Entry======================"); Set<Map.Entry<String, String>> entries = linkedHashMap.entrySet(); System.out.println(entries); // 10. `int size()`:返回Map集合中的key-value数量 System.out.println("======================size======================"); int size = linkedHashMap.size(); System.out.println(size); // 11. `void clear()`:清空Map集合所有元素 System.out.println("======================clear======================"); System.out.println(size); linkedHashMap.clear(); System.out.println(linkedHashMap.size()); // 12. `boolean isEmpty()`:判断Map集合是否为空 System.out.println("======================isEmpty======================"); boolean empty = linkedHashMap.isEmpty(); System.out.println(empty); // 添加数据 linkedHashMap.put("pink", "粉"); System.out.println(linkedHashMap); empty = linkedHashMap.isEmpty(); System.out.println(empty); } }6. Map接口之HashTable实现类(熟悉)
1. HashTable类概述
HashTable与HashMap几乎相同,包括底层数据结构,唯一的区别在于HashMap是线程不安全的,HashTable是线程安全,除此之外所有的使用都相同 HashTable是线程安全的,其方法使用的有
synchronized
关键字修饰2. HashTable构造方法
// 空参构造方法用于创建Hashtable对象 public Hashtable() { // 默认容量大小为11 this(11, 0.75f); } // 指定自定义容量大小创建Hashtable对象 public Hashtable(int initialCapacity) { this(initialCapacity, 0.75f); } // 指定Map集合创建Hashtable对象 public Hashtable(Map<? extends K, ? extends V> t) { this(Math.max(2*t.size(), 11), 0.75f); putAll(t); }3. HashTable常用方法
V put(K key, V value)
:向Map集合中添加元素(键值对元素),如果添加的可以是重复的则会覆盖value值(key不覆盖)
V get(Object key)
:通过指定key获取value值
default V getOrDefault(Object key, V defaultValue)
:通过key获取value值,如果此key不存在则使用默认值输出
V remove(Object key)
:通过指定key移除key和value
boolean containsKey(Object key)
:判断Map集合中是否包含指定key
boolean containsValue(Object value)
:判断集合中是否包含指定value
Collection<V> values()
:返回Map集合中的所有value值
Set<K> keySet()
:返回Map集合中的所有key值
Set<Map.Entry<K, V>> entrySet()
:返回Map集合中的所有key-value值(返回所有键值对)
返回值为Set集合,Set集合中有一个Entry接口,其中包含了获取Key和Value的方法
K getKey()
:获取Entry中的key值
V getValue()
:获取Entry中的value值
int size()
:返回Map集合中的key-value数量
void clear()
:清空Map集合所有元素
boolean isEmpty()
:判断Map集合是否为空
public synchronized Enumeration<V> elements()
:返回此集合数据
public synchronized Enumeration<K> keys()
:返回此集合的key4. HashTable代码案例
public class Demo { public static void main(String[] args) { // 创建Hashtable对象 Hashtable<String, String> hashtable = new Hashtable<>(); // 1. `V put(K key, V value)`:向Map集合中添加元素(键值对元素),如果添加的可以是重复的则会覆盖value值(key不覆盖) System.out.println("======================put======================"); hashtable.put("chi", "小赤"); hashtable.put("cheng", "小橙"); hashtable.put("huang", "小黄"); hashtable.put("lv", "小绿"); hashtable.put("qing", "小青"); hashtable.put("lan", "小蓝"); hashtable.put("zi", "小紫"); hashtable.put("jishi", "鸡屎黄"); hashtable.put("yashi", "鸭屎绿"); // 输出结果 System.out.println(hashtable); // 2. `V get(Object key)`:通过指定key获取value值 System.out.println("======================get======================"); String lv = hashtable.get("lv"); System.out.println(lv); lv = hashtable.get("lv1"); System.out.println(lv); // 3. `default V getOrDefault(Object key, V defaultValue)`:通过key获取value值,如果此key不存在则使用默认值输出 System.out.println("======================getOrDefault======================"); lv = hashtable.getOrDefault("lv", "暂无数据"); System.out.println(lv); lv = hashtable.getOrDefault("lv1", "暂无数据"); System.out.println(lv); // 4. `V remove(Object key)`:通过指定key移除key和value System.out.println("======================remove======================"); String jishi = hashtable.remove("jishi"); System.out.println(jishi); jishi = hashtable.remove("jishi"); System.out.println(jishi); System.out.println(hashtable); // 5. `boolean containsKey(Object key)`:判断Map集合中是否包含指定key System.out.println("======================containsKey======================"); boolean cheng = hashtable.containsKey("cheng"); System.out.println(cheng); cheng = hashtable.containsKey("cheng1"); System.out.println(cheng); // 6. `boolean containsValue(Object value)`:判断集合中是否包含指定value System.out.println("======================containsValue======================"); cheng = hashtable.containsValue("鸭屎绿"); System.out.println(cheng); cheng = hashtable.containsValue("cheng1"); System.out.println(cheng); // 7. `Collection<V> values()`:返回Map集合中的所有value值 System.out.println("======================values======================"); Collection<String> values = hashtable.values(); System.out.println(values); // 8. `Set<K> keySet()`:返回Map集合中的所有key值 System.out.println("======================keySet======================"); Set<String> keySet = hashtable.keySet(); System.out.println(keySet); // 9. `Set<Map.Entry<K, V>> entrySet()`:返回Map集合中的所有key-value值(返回所有键值对) // 1. 返回值为Set集合,Set集合中有一个Entry接口,其中包含了获取Key和Value的方法 // 1. `K getKey()`:获取Entry中的key值 // 2. `V getValue()`:获取Entry中的value值 System.out.println("======================Entry======================"); Set<Map.Entry<String, String>> entries = hashtable.entrySet(); System.out.println(entries); // 10. `int size()`:返回Map集合中的key-value数量 System.out.println("======================size======================"); int size = hashtable.size(); System.out.println(size); // 11. `void clear()`:清空Map集合所有元素 System.out.println("======================clear======================"); System.out.println(size); hashtable.clear(); System.out.println(hashtable.size()); // 12. `boolean isEmpty()`:判断Map集合是否为空 System.out.println("======================isEmpty======================"); boolean empty = hashtable.isEmpty(); System.out.println(empty); // 添加数据 hashtable.put("pink", "粉"); hashtable.put("chi", "小赤"); hashtable.put("cheng", "小橙"); hashtable.put("huang", "小黄"); hashtable.put("lv", "小绿"); hashtable.put("qing", "小青"); hashtable.put("lan", "小蓝"); hashtable.put("zi", "小紫"); hashtable.put("jishi", "鸡屎黄"); hashtable.put("yashi", "鸭屎绿"); System.out.println(hashtable); empty = hashtable.isEmpty(); System.out.println(empty); System.out.println("================================="); // 13. `public synchronized Enumeration<V> elements()`:返回此集合数据 System.out.println("================================="); Enumeration<String> elements = hashtable.elements(); System.out.println(elements); while (elements.hasMoreElements()) { String nextElement = elements.nextElement(); System.out.println(nextElement); } // 14. `public synchronized Enumeration<K> keys()`:返回此集合的key System.out.println("================================="); Enumeration<String> keys = hashtable.keys(); System.out.println(keys); while (keys.hasMoreElements()) { String nextElement = keys.nextElement(); System.out.println(nextElement); } } }7. Map接口之TreeMap实现类(了解熟悉)
1. TreeMap概述
TreeMap是Map的一个子孙类,他是一个有序的Key-Value集合,并且底层是使用于红黑树实现,TreeMap底层是直接使用红黑树,定义为
Entry root
,这也是TreeMap的核心代码private transient Entry<K,V> root;
这段定义就是TreeMap的底层// 红黑树的底层实现 static final class Entry<K,V> implements Map.Entry<K,V> { // Key值 K key; // value值 V value; // 左子树 Entry<K,V> left; // 右子树 Entry<K,V> right; // 父级 Entry<K,V> parent; // 代表红黑树-->默认是Black(黑树) boolean color = BLACK; Entry(K key, V value, Entry<K,V> parent) { this.key = key; this.value = value; this.parent = parent; } }2. TreeMap构造方法
// 空参构造方法用于创建TreeMap对象 public TreeMap() { comparator = null; } // 指定Map集合当做参数创建TreeMap对象 public TreeMap(Map<? extends K, ? extends V> m) { comparator = null; putAll(m); } // 指定比较器创建TreeMap对象 public TreeMap(Comparator<? super K> comparator) { this.comparator = comparator; }3. TreeMap常用方法-->Map集合中有的方法全都可以使用
public V put(K key, V value)
:向集合中添加key-value元素
public V get(Object key)
:通过指定key获取value值
public Set<K> keySet()
:获取集合中的所有key值
public Collection<V> values()
:获取集合中的所有value值
public int size()
:获取集合中元素数量
public void clear()
:清空集合中的元素
public boolean isEmpty()
:判断集合是否为空4. TreeMap代码案例
public class Demo { public static void main(String[] args) { // 创建TreeMap集合对象 TreeMap<String, String> treeMap = new TreeMap<>(); // 1. `public V put(K key, V value)`:向集合中添加key-value元素 System.out.println("=======================put======================="); treeMap.put("name", "基尼太美"); treeMap.put("age", "35"); treeMap.put("sex", "未知"); treeMap.put("sex", "妖"); treeMap.put("hobby", "唱,跳,rap,篮球"); System.out.println(treeMap); // 2. `public V get(Object key)`:通过指定key获取value值 System.out.println("=======================get======================="); String hobby = treeMap.get("hobby"); System.out.println(hobby); // 3. `public Set<K> keySet()`:获取集合中的所有key值 System.out.println("=======================keySet======================="); Set<String> keySet = treeMap.keySet(); System.out.println(keySet); // 4. `public Collection<V> values()`:获取集合中的所有value值 System.out.println("=======================values======================="); Collection<String> values = treeMap.values(); System.out.println(values); // 5. `public int size()`:获取集合中元素数量 System.out.println("=======================size======================="); int size = treeMap.size(); System.out.println(size); // 6. `public void clear()`:清空集合中的元素 System.out.println("=======================clear======================="); treeMap.clear(); // 7. `public boolean isEmpty()`:判断集合是否为空 System.out.println("=======================isEmpty======================="); boolean empty = treeMap.isEmpty(); System.out.println(empty); } }6. TreeMap比较器构造方法(了解熟悉)
使用TreeMap构造方法的比较器,在创建对象时使用外部比较器(匿名内部类),按照升序或降序比较 如果是Java内部的类则不需要使用内部比较器,如果是非内部类则需要实现内部比较器-->实现
Comparable
接口
比较器代码
public class Demo { public static void main(String[] args) { // 使用TreeMap集合传入对象 // TreeMap通过Key排序,如果使用Java提供类则一般会实现比较器,此时则默认正序 // 如果想要实现逆序则需要使用TreeMap集合中的自定义比较器 TreeMap<String, Student> treeMap = new TreeMap<>(); // 定义Student对象 treeMap.put("5", new Student("小明", 18)); treeMap.put("7", new Student("小白", 17)); treeMap.put("1", new Student("小蓝", 19)); treeMap.put("6", new Student("小红", 18)); treeMap.put("3", new Student("小黄", 16)); treeMap.put("2", new Student("小绿", 18)); treeMap.put("4", new Student("小青", 17)); // 输出结果 System.out.println(treeMap); // 使用自定义比较器 TreeMap<String, Student> treeMap1 = new TreeMap<>(new Comparator<String>() { /** * 实现外部比较器的方法 * @param o1 对象1 * @param o2 对象2 * @return 返回结果如果是负数则小, 0则相同, 正数则大 */ @Override public int compare(String o1, String o2) { // 对比两个String值的大小 // 如果o2调用者小于o1则向后排序,如果大则向前排序 return o2.compareTo(o1); } }); // 定义Student对象 treeMap1.put("5", new Student("小明", 18)); treeMap1.put("7", new Student("小白", 17)); treeMap1.put("1", new Student("小蓝", 19)); treeMap1.put("6", new Student("小红", 18)); treeMap1.put("3", new Student("小黄", 16)); treeMap1.put("2", new Student("小绿", 18)); treeMap1.put("4", new Student("小青", 17)); // 输出结果 System.out.println(treeMap1); // 使用实体类当做key值 TreeMap<Student, String> treeMap2 = new TreeMap<>(new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { return o2.getAge() - o1.getAge(); } }); // 添加数据 treeMap2.put(new Student("小明", 16), ""); treeMap2.put(new Student("小明", 12), ""); treeMap2.put(new Student("小明", 11), ""); treeMap2.put(new Student("小明", 13), ""); treeMap2.put(new Student("小明", 15), ""); treeMap2.put(new Student("小明", 14), ""); System.out.println(treeMap2); TreeMap<Student, String> treeMap3 = new TreeMap<>(); // 添加数据 treeMap3.put(new Student("小明", 16), ""); treeMap3.put(new Student("小明", 12), ""); treeMap3.put(new Student("小明", 11), ""); treeMap3.put(new Student("小明", 13), ""); treeMap3.put(new Student("小明", 15), ""); treeMap3.put(new Student("小明", 14), ""); System.out.println(treeMap3); } }4. Map集合总结以及常用实现类(掌握)
1. Map接口实现类区别
Map集合普遍都是Key-Value集合形式,并且所有的Key都不允许重复 HashMap底层是由哈希表实现,JDK1.8后如果存储数据超过8个则改为红黑树 LinkedHashMap底层是由哈希表+链表实现,不论数据长短都是相同,有序集合 HashTable底层与HashMap相同,但是是线程安全的 TreeMap底层是红黑树实现
2. Map接口常用方法
V put(K key, V value)
:向Map集合中添加元素(键值对元素),如果添加的可以是重复的则会覆盖value值(key不覆盖)
V get(Object key)
:通过指定key获取value值
V remove(Object key)
:通过指定key移除key和value
boolean containsKey(Object key)
:判断Map集合中是否包含指定key
boolean containsValue(Object value)
:判断集合中是否包含指定value
Set<Map.Entry<K, V>> entrySet()
:返回Map集合中的所有key-value值(返回所有键值对)
int size()
:返回Map集合中的key-value数量
boolean isEmpty()
:判断Map集合是否为空3. Map集合的创建方式以及常用实现类
Map集合创建方式常用多态方式创建,所以使用时只能使用Map接口定义的方法,如果后期会使用到实现类的某些方法则单独创建 Map接口的常用实现类是HashMap类,后期使用他最多
4. Map集合常用方法使用以及多态方式创建对象
public class Demo { public static void main(String[] args) { // 多态方式创建Map集合对象 Map<String, List<String>> map = new HashMap<>(); // 定义List集合 List<String> list1 = new ArrayList<>(); // 向List集合中添加数据 list1.add("锄禾日当午"); list1.add("汗滴禾下土"); list1.add("谁知盘中餐"); list1.add("粒粒皆辛苦"); List<String> list2 = new ArrayList<>(); // 向List集合中添加数据 list2.add("床前明月光"); list2.add("疑是地上霜"); list2.add("举头望明月"); list2.add("低头思故乡"); List<String> list3 = new ArrayList<>(); // 向List集合中添加数据 list3.add("君问归期未有期"); list3.add("巴山夜雨涨秋池"); list3.add("何当共剪西窗烛"); list3.add("却话巴山夜雨时"); // 将古诗添加到Map集合中 map.put("悯农", list1); map.put("静夜思", list2); map.put("夜雨寄北", list3); System.out.println(map); // 通过key查询map集合,如果存在则输出结果如果不存在则输出不存在 // 第一种方式使用查询key判断 // map.containsKey() String name = "悯农1"; if (map.containsKey(name)) { System.out.println(map.get(name)); } else { System.out.println("古诗<" + name + ">不存在!"); } // list集合添加Map集合数据 Map<String, String> map1 = new HashMap<>(); map1.put("name", "基尼太美"); map1.put("age", "35"); map1.put("sex", "未知"); map1.put("sex", "妖"); map1.put("hobby", "唱,跳,rap,篮球"); Map<String, String> map2 = new HashMap<>(); map2.put("name", "基尼太美"); map2.put("age", "35"); map2.put("sex", "未知"); map2.put("sex", "妖"); map2.put("hobby", "唱,跳,rap,篮球"); Map<String, String> map3 = new HashMap<>(); map3.put("name", "基尼太美"); map3.put("age", "35"); map3.put("sex", "未知"); map3.put("sex", "妖"); map3.put("hobby", "唱,跳,rap,篮球"); // 定义List集合 List<Map<String, String>> list = new ArrayList<>(); // 向集合中添加数据 list.add(map1); list.add(map2); list.add(map3); System.out.println(list); // 对于以上两种集合遍历 // 遍历Map集合 Set<String> keySet = map.keySet(); // 遍历KeySet集合 for (String key : keySet) { // 打印key值 System.out.println(key); // 通过key获取value值 List<String> tempList = map.get(key); // 遍历value数据 for (String values : tempList) { System.out.println("----" + values); } } // List集合遍历 for (Map<String, String> objectMap : list) { // 遍历map集合 Set<String> keySet1 = objectMap.keySet(); for (String key : keySet1) { String value = objectMap.get(key); System.out.println(key + "----" + value); } } } }6 . Set接口(掌握)
1. Set概述
Set接口继承自Collection接口,在Set接口中所有方法基本与Collection相同,除此之外,没有任何相同内容,具体实现也不是自己写的 Set集合是一个无序(无序是指插入顺序与取出顺序不一致),且不可重复集合,Set集合中的元素与HashMap的key的值相同属性 Set集合分为三个实现类1. HashSet,2. LinkedHashSet,3. TreeSet
2. Set常用方法
3. Set接口之HashSet实现类(熟悉/掌握)
1. HashSet概述
HashSet是Set接口的直接子类,但又不完全依赖于Set接口,原因是其内部实现是使用HashMap集合的方式(Set集合与Map集合的关系就是继父,继子关系) HashSet集合的具体实现是由HashMap集合的方法组成-->
private transient HashMap<E,Object> map;
HashSet集合中创建的Map对象2. HashSet构造方法
// 创建HashSet集合对象 public HashSet() { // 在创建HashSet对象时一并创建HashMap对象 map = new HashMap<>(); } // 指定初始化容量创建HashSet对象 public HashSet(int initialCapacity) { map = new HashMap<>(initialCapacity); } // 指定Collection集合创建HashSet对象 public HashSet(Collection<? extends E> c) { map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); addAll(c); }3. HashSet常用方法
public boolean add(E e)
:向集合中添加元素
public boolean contains(Object o)
:判断是否存在某个元素
public boolean remove(Object o)
:从集合中移除指定元素
public int size()
:返回集合元素数量(集合长度)
public boolean isEmpty()
:判断集合是否为空
public void clear()
:清空集合中的所有元素
public Iterator<E> iterator()
:返回Set集合的迭代器对象4. HashSet代码案例
public class Demo { public static void main(String[] args) { // 创建HashSet集合对象 HashSet<String> set = new HashSet<>(); // 1. `public boolean add(E e)`:向集合中添加元素 set.add("菜虚鲲"); set.add("刘亦菲"); set.add("鞠婧祎"); set.add("古天乐"); set.add("梅超风"); set.add("裘千尺"); System.out.println(set); // 2. `public boolean contains(Object o)`:判断是否存在某个元素 System.out.println("==============================="); boolean isContains = set.contains("菜虚鲲"); System.out.println(isContains); isContains = set.contains("菜虚鲲1"); System.out.println(isContains); // 3. `public boolean remove(Object o)`:从集合中移除指定元素 System.out.println("==============================="); boolean isRemove = set.remove("裘千尺"); System.out.println(isRemove); isRemove = set.remove("裘千尺"); System.out.println(isRemove); // 4. `public int size()`:返回集合元素数量(集合长度) System.out.println("==============================="); System.out.println(set); int size = set.size(); System.out.println(size); // 5. `public boolean isEmpty()`:判断集合是否为空 System.out.println("==============================="); boolean empty = set.isEmpty(); System.out.println(empty); // 7. `public Iterator<E> iterator()`:返回Set集合的迭代器对象 System.out.println("==============================="); Iterator<String> iterator = set.iterator(); while (iterator.hasNext()) { // 输出结果 String next = iterator.next(); System.out.println(next); } // 6. `public void clear()`:清空集合中的所有元素 System.out.println("==============================="); set.clear(); System.out.println(set); System.out.println(set.size()); System.out.println(set.isEmpty()); } }4. Set接口之LinkedHashSet实现类(了解)
1. LinkedHashSet概述
LinkedHashSet是Set接口的实现类,方法与Set接口大致相同,与HashSet用法也大致相同,唯一的却别在于LinkedHashSet是有序集合,同样底层通过Map集合实现 此时LinkedHashSet已经开始不背人,直接继承HashSet,区别在于调用的是HashSet中的创建LinkedHashMap的构造方法 调用的构造方法如下
// HashSet的构造方法 HashSet(int initialCapacity, float loadFactor, boolean dummy) { // 创建对象时改为LinkedHashMap对象 map = new LinkedHashMap<>(initialCapacity, loadFactor); }2. LinkedHashSet构造方法
// 创建LinkedHashSet对象 public LinkedHashSet() { super(16, .75f, true); } // 创建LinkedHashSet对象并是这初始化容量 public LinkedHashSet(int initialCapacity) { super(initialCapacity, .75f, true); } // 创建LinkedHashSet对象并添加指定集合数据 public LinkedHashSet(Collection<? extends E> c) { super(Math.max(2*c.size(), 11), .75f, true); addAll(c); }3. LinkedHashSet常用方法
public boolean add(E e)
:向集合中添加元素
public boolean contains(Object o)
:判断是否存在某个元素
public boolean remove(Object o)
:从集合中移除指定元素
public int size()
:返回集合元素数量(集合长度)
public boolean isEmpty()
:判断集合是否为空
public void clear()
:清空集合中的所有元素
public Iterator<E> iterator()
:返回Set集合的迭代器对象4. LinkedHashSet代码案例
public class Demo { public static void main(String[] args) { // 创建LinkedHashSet集合对象 LinkedHashSet<String> set = new LinkedHashSet<>(); // 1. `public boolean add(E e)`:向集合中添加元素 set.add("菜虚鲲"); set.add("刘亦菲"); set.add("鞠婧祎"); set.add("古天乐"); set.add("梅超风"); set.add("裘千尺"); System.out.println(set); // 2. `public boolean contains(Object o)`:判断是否存在某个元素 System.out.println("==============================="); boolean isContains = set.contains("菜虚鲲"); System.out.println(isContains); isContains = set.contains("菜虚鲲1"); System.out.println(isContains); // 3. `public boolean remove(Object o)`:从集合中移除指定元素 System.out.println("==============================="); boolean isRemove = set.remove("裘千尺"); System.out.println(isRemove); isRemove = set.remove("裘千尺"); System.out.println(isRemove); // 4. `public int size()`:返回集合元素数量(集合长度) System.out.println("==============================="); System.out.println(set); int size = set.size(); System.out.println(size); // 5. `public boolean isEmpty()`:判断集合是否为空 System.out.println("==============================="); boolean empty = set.isEmpty(); System.out.println(empty); // 7. `public Iterator<E> iterator()`:返回Set集合的迭代器对象 System.out.println("==============================="); Iterator<String> iterator = set.iterator(); while (iterator.hasNext()) { // 输出结果 String next = iterator.next(); System.out.println(next); } // 6. `public void clear()`:清空集合中的所有元素 System.out.println("==============================="); set.clear(); System.out.println(set); System.out.println(set.size()); System.out.println(set.isEmpty()); } }5. Set接口之TreeSet实现类(了解)
1. TreeSet概述
TreeSet底层是由TreeMap实现,内部直接调用TreeMap方法,相当于一个小号的TreeMap集合,同样也是单列集合,同样通过Key存储数据 使用时同样是按照比较器添加数据,如果是自定义实体类想向TreeSet集合中添加数据必须实现
Comparable
接口,或者使用匿名内部类方式才可以,否则会出现异常 TreeSet底层实现// 声明变量,用于创建TreeMap集合对象 private transient NavigableMap<E,Object> m; // 构造方法用于给NavigableMap集合初始值 TreeSet(NavigableMap<E,Object> m) { this.m = m; } // 创建TreeSet集合对象 public TreeSet() { // 调用上面的构造方法,并创建TreeMap集合对象 this(new TreeMap<E,Object>()); }2. TreeSet构造方法
// 创建TreeSet集合对象 public TreeSet() { // 调用上面的构造方法,并创建TreeMap集合对象 this(new TreeMap<E,Object>()); } // 指定Collection集合参数创建TreeSet集合对象 public TreeSet(Collection<? extends E> c) { this(); addAll(c); } // 指定比较器创建TreeSet集合对象 public TreeSet(Comparator<? super E> comparator) { this(new TreeMap<>(comparator)); }3. TreeSet常用方法
public boolean add(E e)
:向集合中添加元素
public boolean contains(Object o)
:判断是否存在某个元素
public boolean remove(Object o)
:从集合中移除指定元素
public int size()
:返回集合元素数量(集合长度)
public boolean isEmpty()
:判断集合是否为空
public void clear()
:清空集合中的所有元素
public Iterator<E> iterator()
:返回Set集合的迭代器对象4. TreeSet代码案例
public class Demo { public static void main(String[] args) { // 使用Java内部提供的类创建TreeMap集合对象 TreeSet<String> set = new TreeSet<>(); // 1. `public boolean add(E e)`:向集合中添加元素 set.add("6"); set.add("4"); set.add("2"); set.add("3"); set.add("5"); set.add("1"); System.out.println(set); // 2. `public boolean contains(Object o)`:判断是否存在某个元素 System.out.println("==============================="); boolean isContains = set.contains("菜虚鲲"); System.out.println(isContains); isContains = set.contains("菜虚鲲1"); System.out.println(isContains); // 3. `public boolean remove(Object o)`:从集合中移除指定元素 System.out.println("==============================="); boolean isRemove = set.remove("裘千尺"); System.out.println(isRemove); isRemove = set.remove("裘千尺"); System.out.println(isRemove); // 4. `public int size()`:返回集合元素数量(集合长度) System.out.println("==============================="); System.out.println(set); int size = set.size(); System.out.println(size); // 5. `public boolean isEmpty()`:判断集合是否为空 System.out.println("==============================="); boolean empty = set.isEmpty(); System.out.println(empty); // 7. `public Iterator<E> iterator()`:返回Set集合的迭代器对象 System.out.println("==============================="); Iterator<String> iterator = set.iterator(); while (iterator.hasNext()) { // 输出结果 String next = iterator.next(); System.out.println(next); } // 6. `public void clear()`:清空集合中的所有元素 System.out.println("==============================="); set.clear(); System.out.println(set); System.out.println(set.size()); System.out.println(set.isEmpty()); System.out.println("==============================="); // 使用匿名内部类更改比较器顺序 // 使用Java内部提供的类创建TreeMap集合对象 TreeSet<String> set1 = new TreeSet<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); // 1. `public boolean add(E e)`:向集合中添加元素 set1.add("6"); set1.add("4"); set1.add("2"); set1.add("3"); set1.add("5"); set1.add("1"); System.out.println(set1); System.out.println("==============================="); // 使用实体类添加set集合数据 TreeSet<Student> set2 = new TreeSet<>(new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { // Student对象是没有比较方法的,所以直接调用其属性的比较方法即可 // 如果是字符串调用compareTo方法 // 如果是数字类型则直接减法运算即可 // 使用年龄升序 return o1.getAge() - o2.getAge(); } }); // 添加数据 set2.add(new Student("裘千尺", 15)); set2.add(new Student("梅超风", 11)); set2.add(new Student("黑山老妖", 16)); set2.add(new Student("肾虚公子", 14)); set2.add(new Student("黑风怪", 12)); set2.add(new Student("裘千仞", 17)); set2.add(new Student("灭绝师太", 13)); // 输出结果 System.out.println(set2); System.out.println("==============================="); // 使用内部比较器比较-->Student实现Comparable接口即可 // 使用实体类添加set集合数据 TreeSet<Student> set3 = new TreeSet<>(); // 添加数据 set3.add(new Student("裘千尺", 15)); set3.add(new Student("梅超风", 11)); set3.add(new Student("黑山老妖", 16)); set3.add(new Student("肾虚公子", 14)); set3.add(new Student("黑风怪", 12)); set3.add(new Student("裘千仞", 17)); set3.add(new Student("灭绝师太", 13)); // 输出结果 System.out.println(set3); } }6. Set接口实现类总结(掌握)
1. Set接口实现类区别
Set接口的实现类没有区别,都是使用的Map接口的实现类直接调用,实现Set的方法 Set接口的实现类统一无序(LinkedHashMap是有序的),且内容不能重复 底层实现对照Map接口实现类对应
2. Set接口常用方法
public boolean add(E e)
:向集合中添加元素
public boolean contains(Object o)
:判断是否存在某个元素
public boolean remove(Object o)
:从集合中移除指定元素
public int size()
:返回集合元素数量(集合长度)
public boolean isEmpty()
:判断集合是否为空
public void clear()
:清空集合中的所有元素
public Iterator<E> iterator()
:返回Set集合的迭代器对象3. Set接口实现类创建对象
Set接口实现类创建对象方式一般使用多态创建,所有方法使用的都是Set预先定义好的,所以会用即可 创建对象方式例如:
Set<泛型类型> 变量名 = new 实现类<>();
3. Set接口代码案例以及Set接口存放自定义对象测试
添加自定义对象时是否会重复验证 向Set集合中添加实体类对象会出现数据重复的问题,原因是Set集合都是通过Map集合实现的,所以使用的add方法的实现是put方法,而Map集合的put方法在验证时是使用
equals
和hashCode
来验证是否是相同的元素,所以实体类对象就必须重写equals
和hashCode
方法才能让元素不重复public class Demo { public static void main(String[] args) { System.out.println("==============================="); // 使用实体类添加set集合数据 HashSet<Student> set = new HashSet<>(); // 添加数据 set.add(new Student("裘千尺", 15)); set.add(new Student("梅超风", 11)); set.add(new Student("黑山老妖", 16)); set.add(new Student("肾虚公子", 14)); set.add(new Student("黑风怪", 12)); set.add(new Student("裘千仞", 17)); set.add(new Student("灭绝师太", 13)); // 添加重复数据 set.add(new Student("裘千尺", 15)); set.add(new Student("梅超风", 11)); set.add(new Student("黑山老妖", 16)); set.add(new Student("肾虚公子", 14)); set.add(new Student("黑风怪", 12)); set.add(new Student("裘千仞", 17)); set.add(new Student("灭绝师太", 13)); // 输出结果 System.out.println(set.size()); System.out.println(set); System.out.println("==============================="); HashSet<String> set1 = new HashSet<>(); set1.add(new String("abc")); set1.add(new String("abc")); set1.add(new String("abc")); set1.add(new String("deg")); set1.add(new String("saf")); set1.add(new String("gdfsd")); set1.add(new String("bdf")); set1.add(new String("deg")); set1.add(new String("saf")); set1.add(new String("gdfsd")); set1.add(new String("bdf")); System.out.println(set1.size()); System.out.println(set1); } }7. 比较器(了解熟悉)
1. 比较器概述
比较器的作用是用于集合中的排序使用
2. 比较器使用方式
比较器使用方式分为两种,第一种是实现
Comparable
接口,第二种是使用匿名内部类创建Comparable
1. 实现
Comparable
接口是内部比较器代码案例 实体类
/** * 实现Comparable接口,并且重写compareTo方法,完成比较器的比较方式 */ public class Student implements Comparable<Student> { /** * @param student 传入参数 * @return 返回整数类型,-1小于,0相同,1大于 */ public int compareTo(Student student) { // 使用this对象对比 return student.getAge() - this.age; } private String name; private Integer age; public Student() { } public Student(String name, Integer age) { this.name = name; this.age = age; } 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; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }测试案例
public class Demo { public static void main(String[] args) { System.out.println("===============使用内部比较器==============="); // 使用实体类添加set集合数据 TreeSet<Student> set1 = new TreeSet<>(); // 添加数据 set1.add(new Student("裘千尺", 15)); set1.add(new Student("梅超风", 11)); set1.add(new Student("黑山老妖", 16)); set1.add(new Student("肾虚公子", 14)); set1.add(new Student("黑风怪", 12)); set1.add(new Student("裘千仞", 17)); set1.add(new Student("灭绝师太", 13)); // 输出结果 System.out.println(set1); } }2. 匿名内部类创建
Comparator
是外部比较器代码案例 实体类
/** * Student实体类对象 */ public class Student { private String name; private Integer age; public Student() { } public Student(String name, Integer age) { this.name = name; this.age = age; } 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; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }测试案例
public class Demo { public static void main(String[] args) { System.out.println("===============使用外部比较器==============="); // 使用内部比较器比较-->Student实现Comparable接口即可 // 使用实体类添加set集合数据 TreeSet<Student> set2 = new TreeSet<>(new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { // 使用年龄倒序排序 return o2.getAge() - o1.getAge(); } }); // 添加数据 set2.add(new Student("裘千尺", 15)); set2.add(new Student("梅超风", 11)); set2.add(new Student("黑山老妖", 16)); set2.add(new Student("肾虚公子", 14)); set2.add(new Student("黑风怪", 12)); set2.add(new Student("裘千仞", 17)); set2.add(new Student("灭绝师太", 13)); // 输出结果 System.out.println(set2); } }8. Collections工具类(熟悉)
1. Collections概述
这个类只包含操作或返回集合的静态方法。它包含多态算法操作的集合,它返回一个按指定的集合支持的新的集合,和其他一些零碎的东西。 说人话就是定义了一系列的操作集合的工具方法
2. Collections常用静态方法
public static <T> boolean addAll(Collection<? super T> c, T... elements)
:向指定集合中添加多条数据
public static final <T> List<T> emptyList()
:返回一个空集合
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
:返回集合中的数据大小
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll)
:返回集合中的数据大小
public static <T extends Comparable<? super T>> void sort(List<T> list)
:排序集合
public static <T> void sort(List<T> list, Comparator<? super T> c)
:自定义排序集合
public static void shuffle(List<?> list)
:混乱排序集合
public static void reverse(List<?> list)
:反转排序集合3. Collections代码案例
max和min较为常用一点
public class Demo { public static void main(String[] args) { // 定义一个List集合 List<Integer> list = new ArrayList<>(); // 添加数据 // list.add(4); // list.add(2); // list.add(5); // list.add(3); // list.add(1); // System.out.println(list); // 1. `public static <T> boolean addAll(Collection<? super T> c, T... elements)`:向指定集合中添加多条数据 System.out.println("=====================addAll====================="); boolean isAddAll = Collections.addAll(list, 4, 2, 5, 3, 1, 9, 6, 8, 7, 10, 14, 12, 13, 11, 15); System.out.println(isAddAll); System.out.println(list); // 2. `public static final <T> List<T> emptyList()`:返回一个空集合 System.out.println("=====================emptyList====================="); // 返回空集合 List<Object> objects = Collections.emptyList(); System.out.println(objects); // 使用时类似于asList方法,一旦返回就是定长集合,不能添加数据 List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5); // integers.add(6); System.out.println(integers); // 3. `public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)`:返回集合中的数据大小 System.out.println("=====================max====================="); int max = 0; for (Integer integer : list) { if (max < integer) { max = integer; } } System.out.println(max); // 返回最大值方法 Integer max1 = Collections.max(list); System.out.println(max1); // 4. `public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll)`:返回集合中的数据大小 System.out.println("=====================min====================="); Integer min = Collections.min(list); System.out.println(min); // 5. `public static <T extends Comparable<? super T>> void sort(List<T> list)`:排序集合 System.out.println("=====================sort====================="); Collections.sort(list); System.out.println(list); // 6. `public static <T> void sort(List<T> list, Comparator<? super T> c)`:自定义排序集合 System.out.println("=====================sort====================="); Collections.sort(list, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { // 设置倒序 return o2 - o1; } }); System.out.println(list); // 7. `public static void shuffle(List<?> list)`:混乱排序集合 System.out.println("=====================shuffle====================="); Collections.shuffle(list); System.out.println(list); Collections.shuffle(list); System.out.println(list); Collections.shuffle(list); System.out.println(list); Collections.shuffle(list); System.out.println(list); Collections.shuffle(list); System.out.println(list); // 修改为正序 Collections.sort(list); System.out.println(list); Collections.shuffle(list); System.out.println(list); // 8. `public static void reverse(List<?> list)`:反转排序集合 System.out.println("=====================reverse====================="); Collections.reverse(list); System.out.println(list); } }9. 总结
List集合常用的是ArrayList Map集合常用的是HashMap Set集合常用的是HashSet 其他集合,仅做对比以及区别牢记,只要上面的三个用熟练了,其他的集合也是会用的 泛型在集合中的使用认真看,泛型的定义与使用当前阶段认真练
01-12
01-01
431
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交