主要知识点:
- 集合的概念:理解集合的概念和定义
- Collection 接口:掌握Collection接口的作用及其运用
- List接口及其子类:熟练掌握List接口及其子类的用法
- Set接口及其子类:熟练掌握Set接口及其子类的用法
- Map接口及其子类:熟练掌握Map接口及其子类的用法,了解Collection接口与Map接口的区别
- 集合的输出:熟练掌握并运用迭代输出Iterator类和foreach类
- Collections 工具类:熟练掌握并且可以运用Collections的方法
总结:
Collection接口:
— List 有序,可重复
ArrayList
优点: 底层数据结构是数组,查询快,增删慢。
缺点: 线程不安全,效率高
Vector
优点: 底层数据结构是数组,查询快,增删慢。
缺点: 线程安全,效率低
LinkedList
优点: 底层数据结构是链表,查询慢,增删快。
缺点: 线程不安全,效率高
—Set 无序,唯一
HashSet
底层数据结构是哈希表。(无序,唯一)
如何来保证元素唯一性?
1.依赖两个方法:hashCode()和equals()
LinkedHashSet
底层数据结构是链表和哈希表。(FIFO插入有序,唯一)
1.由链表保证元素有序
2.由哈希表保证元素唯一
TreeSet
底层数据结构是红黑树。(唯一,有序)
- 如何保证元素排序的呢?
自然排序
比较器排序
2.如何保证元素唯一性的呢?
根据比较的返回值是否是0来决定
集合的概念
集合又称为类集或者容器。
集合和数组的区别:
- 都是容器,数组时固定的长度,集合时可变的;
- 数组存放的数据都是基本数据类型(四类八种)集合存放的数据都是引用数据类型(String、Integer、自定义数据类型)
- 集合中对于基本数据类型会转换位引用数据类型再存储。
Java 中的集合类主要由两个接口派生,即 Collection 和 Map。
Collection接口
java.util.Collection 是集合类的基本接口,它位于集合类的顶层。Collection 接口的定义:
public interface Collection<E> extends Iterable<E>
Collection 使用泛型技术,所以在操作时必须指定具体的操作类型,有利于
集合的安全性。Collection 是 List 接口和 Set 接口的父接口。
Collection 接口的主要子接口有如下几个。
- List:集合中的元素按照索引值来排序,允许存放重复的元素。List 集合数
组相似。 - Queue:队列接口,队列通常以 FIFO(先进先出)的方式排序各个元素。
- Set:集合中的元素不按特定方式排序,不能存在重复对象,但它的有些实现类能对集合中的元素按照特定方式排序。
- SortedSet:可以对集合中的元素进行排序
List接口:有序,可重复
特性:
- List集合是一个有序的、可重复的集合,集合中每一个元素都有对应的顺序索引。
- List允许加入重复元素是应为可以通过索引来访问指定位置的元素。
- List集合默认按照元素的添加顺序增加元素的索引。
ArrayList接口
ArrayList是基于数组实现的List类,实现所有可选列表操作,允许所有元素包括null。
主要方法
boolean add(E e) -->将指定的元素追加到此列表的末尾。
void add(int index, E element) -->在此列表中的指定位置插入指定的元素。
boolean addAll(Collection<? extends E> c) -->按指定集合的Iterator返回的顺序将指定集合中的所有元素追加到此列表的末尾。
boolean addAll(int index, Collection<? extends E> c) -->将指定集合中的所有元素插入到此列表中,从指定的位置开始。
boolean contains(Object o) -->如果此列表包含指定的元素,则返回 true 。
E get(int index) -->返回此列表中指定位置的元素。
E remove(int index) -->删除该列表中指定位置的元素。
E set(int index, E element) -->用指定的元素替换此列表中指定位置的元素。
Object[] toArray() -->以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。
ArrayList数组操作练习
package pers.hwh.collection;
import java.util.*;
public class ArrayListDemo1 {
public static void main(String[] args) {
Collection<String> collection = new ArrayList<String>();//通过ArrayList实例化Collection
List<String> list = new ArrayList<String>();//通过ArrayList实例化List
collection.add("1");//添加元素
collection.add("2");
collection.add("3");
System.out.println("collection集合:"+collection);
list.add("A");//添加元素
list.add(1,"B");//在指定位置添加元素
list.add("C");
list.addAll(0,collection);//在指定位置添加一个集合的所有元素
System.out.println("list集合:"+list);
list.remove("B");
list.remove(1);
list.removeAll(collection);
System.out.println("删除list集合后:"+list);//打印list集合的所有元素
String[]arr=list.toArray(new String[]{
});//打印将集合转换为字符串数组
for(String a:arr){
//输出数组元素
System.out.print(a+" ");
}
}
}
执行结果:
collection集合:[1, 2, 3]
list集合:[1, 2, 3, A, B, C]
删除list集合后:[A, C]
A C
LinkedList接口
LinkedList指的是链表类的数据结构。
主要方法
void addFirst(E e) -->在该列表开头插入指定的元素。
void addLast(E e) -->将指定的元素追加到此列表的末尾。
E peekFirst() -->检索但不删除此列表的第一个元素,如果此列表为空,则返回 null 。
E peekLast() -->检索但不删除此列表的最后一个元素,如果此列表为空,则返回 null 。
E pollFirst() -->检索并删除此列表的第一个元素,如果此列表为空,则返回 null 。
E pop() -->从此列表表示的堆栈中弹出第一个元素。相似于removeFirst()
void push(E e) -->将元素推送到由此列表表示的堆栈上。相似于addFirst()
LinkedList数组操作练习
package pers.hwh.collection;
import java.util.*;
public class LinkedListDemo1 {
public static void main(String[] args) {
LinkedList<String> link=new LinkedList<String>();
link.add("1"); //添加元素
link.add("2"); //添加元素
link.add("3"); //添加元素
link.addFirst("F"); //添加元素在链表开头处
link.addLast("L"); //添加元素在链表结尾处
LinkedList<String> newLink=new LinkedList<String>(link);
System.out.println("添加元素后:\n\t"+link);
System.out.println("get()方法获取表头:"+link.getFirst());
System.out.println("使用 get()方法后:\n\t"+link);
System.out.println("element()方法获取表头:"+link.element());
System.out.println("使用 element()方法后:\n\t"+link);
System.out.println("peek()方法获取表头:"+link.peek());
System.out.println("使用 peek()方法后:\n\t"+link);
System.out.println("poll()方法获取表头:"+link.poll());
System.out.println("使用 poll()方法后:\n\t"+link);
System.out.println("pop()方法获取表头:"+link.pop());
System.out.println("使用 pop()方法后:\n\t"+link);
System.out.println("****使用链表的先进先出*****");
int len=newLink.size();
for (int i=0;i<len;i++ ){
System.out.print(newLink.poll()+" ");
}
System.out.println();
}
}
执行结果:
添加元素后:
[F, 1, 2, 3, L]
get()方法获取表头:F
使用 get()方法后:
[F, 1, 2, 3, L]
element()方法获取表头:F
使用 element()方法后:
[F, 1, 2, 3, L]
peek()方法获取表头:F
使用 peek()方法后:
[F, 1, 2, 3, L]
poll()方法获取表头:F
使用 poll()方法后:
[1, 2, 3, L]
pop()方法获取表头:1
使用 pop()方法后:
[2, 3, L]
****使用链表的先进先出*****
F 1 2 3 L
ArrayList和LinkedList区别
ArrayList 底层实现就是数组,且ArrayList实现了RandomAccess,表示它能快速随机访问存储的元素,通过下标 index 访问,只是我们需要用 get() 方法的形式, 数组支持随机访问, 查询速度快, 增删元素慢;
LinkedList 底层实现是链表, LinkedList 没有实现 RandomAccess 接口,链表支持顺序访问, 查询速度慢, 增删元素快
大白话解释:
-
ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 这里的所谓动态数组并不是那个“ 有多少元素就申请多少空间 ”的意思,通过查看源码,可以发现,这个动态数组是这样实现的,如果没指定数组大小,则申请默认大小为10的数组,当元素个数增加,数组无法存储时,系统会另个申请一个长度为当前长度1.5倍的数组,然后把之前的数据拷贝到新建的数组。
-
对于随机访问get和set,ArrayList一般情况下优于LinkedList,ArrayList是数组,所以,直接定位到相应位置取元素,LinkedLIst是链表,所以需要从前往后遍历,也就是说,LinkedList不支持高效的随机元素访问。
-
在ArrayList的中间插入或删除一个元素意味着这个列表中剩余的元素都会被移动;而在LinkedList的中间插入或删除一个元素的开销是固定的。
-
ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗的空间。,因为ArrayList空间的增长率为1.5倍,所以,最后很可能留下一部分空间是没有用到的,因此,会造成浪费的情况。对于LInkedList的话,由于每个节点都需要额外的指针。
Set接口:无序,唯一
特性:
Set集合是一个无序的、不可重复的集合。
- Set集合中的对象不按特定方式排序,只是简单地把对象加入集合中。
- Set集合中不允许包含重复的元素,即任意的两个元素e1和e2都有e1.equals(e2)=false。
HashSet接口
HashSet类是按照哈希算法来存取集合中的元素的,使用哈希算法可以提高存取的效率。当HashSet集合中添加元素时,就会调用该元素的hashCode()方法,获取其哈希码值,根据这个哈希码值计算出这个元素的存放位置。
HashSet具有以下特点:
- 不能够保证元素的排列顺序,集合中元素的排列顺序随时有可能发生改变。
- 集合中最多只能存在一个null元素
- 不是线程同步的
举例1:没有重写equals()和hashCode()方法的HashSet集合
public class Person {
private String name;
private int age;
public Person(){
}
public