目录
- 友情提醒
- 第一章、集合体系概述
- 1.1)集合是什么?与数组的区别在哪
- 1.2)集合体系与分类
- 第二章、集合体系中的Collection和List接口/Set接口
- 2.0)List接口/Set接口两者区别
- 2.1)Collection接口中的常用方法
- 2.2)list接口的独有方法
- 2.3)Set接口独有的方法
- 2.4)使用迭代器Iterator 遍历集合元素
- 第三章、List集合下的ArrayList和LinkedList
- 3.1)ArrayList集合
- 3.2)LinkedList集合
- 3.3)Vector集合
- 第四章、Set集合下的HashSet和LinkedHashSet和TreeSet
- 4.0)set集合如何比较
- 4.1)HashSet集合
- 4.2)LinkedHashSet集合
- 4.3)TreeSet集合
- 4.4)从TreeSet讲到Comparable和Comparator接口
- 第五章、Map接口和HashMap集合
- 4.1)
- 4.2)
- 4.3)
友情提醒
先看文章目录,大致了解知识点结构,直接点击文章目录可以跳转到文章指定位置。
第一章、集合体系概述
1.1)集合是什么?与数组的区别在哪
集合与数组类似,都是容器都可以存放数据,但二者有很大的区别。
①长度:
数组:固定长度,无法改变。
集合:长度可改变,可以扩容。
②存储:
数组:可以存储基本类型数据,还可以存储引用类型的数据,但是只能存储相同类型的数据。
集合:只能存储引用类型的数据并且可以存储不同引用类型的数据。
1.2)集合体系与分类
数组只有一种但是集合有很多分类每一种集合都有自己的特点:数据可重复,数据不可重复,数据无序,数据有序,直接存储,单列集合,以key-value形式存储的双列集合等等,最好背下来。
集合大家族如图:图片来自百度
第二章、集合体系中的Collection和List接口/Set接口
Collection集合体系下有两个直接的子接口:List和Set
2.0)List接口/Set接口两者区别
如下表:可以看出来Set很复杂。
特点 | List | Set |
---|---|---|
重复元素 | 可以重复 | 不可重复 |
下标 | 有下标 | 没有下标 |
存储 | 有序,可存储多个null | 无序,只能存一个null |
函数 | 拥有独有函数 | 无特有函数,均来自Collection |
遍历 | 有下标可多种方式遍历 | 无下标只能用迭代器遍历 |
数据结构 | ArrayList:底层是可变数组 | HashSet:数据结构是哈希表,无序 |
数据结构 | LinkedList:底层是链表 | TreeSet:底层数据结构是二叉树,无序 |
数据结构 | Vector:底层是可变数组 | LinkedHashSet:底层是哈希表和链表,与别的set集合不同,它是有序的 |
2.1)Collection接口中的常用方法
大致分为增加,查找和删除数据方法,以及将集合转为数组的方法。
增加集合元素方法,类型转换方法
public class TestCollection {
public static void main(String[] args) {
test3();
}
//-------------------------------分割--增加数据方法--------------------------------
/*
增加操作boolean add(E e):确保此 collection 包含指定的元素(可选操作)。
boolean addAll(Collection<? extends E> c):将指定 collection 中的所有元素
都添加到此 collection 中(可选操作)。 举例:coll.addAll(coll2);*/
public static void test3() {
Collection coll = new ArrayList(); //运用了多态性,方便展示Collection中的方法
coll.add("abc");
coll.add(123);//系统会自动装箱为Integer类型的对象然后再存入集合中
coll.add(3.14);//系统会自动装箱
coll.add(true);
coll.add(new Student("李雷", 20));
coll.add(null);
System.out.println(coll);//打印结果[abc, 123, 3.14, true, Student{name='李雷', age=20}, null]
//类型转换Collection -> 数组
Object[] objs = coll.toArray();
System.out.println(Arrays.toString(objs));//打印结果[abc, 123, 3.14, true, Student{name='李雷', age=20}, null]
//类型转换数组 -> list集合
List list = Arrays.asList(objs);
System.out.println(list);//打印结果[abc, 123, 3.14, true, Student{name='李雷', age=20}, null]
System.out.println(list instanceof ArrayList); //打印结果false
System.out.println(list instanceof List); //打印结果true
System.out.println(list instanceof Collection); //打印结果true
//获取集合元素的个数/容量大小 int size():返回此 collection 中的元素数。
System.out.println(coll.size());
}
查找集合元素
//查找
public static void test2() {
Collection coll = new ArrayList(); //多态
coll.add("abc");
coll.add(123);
coll.add(3.1);
coll.add(true);
coll.add(new Student("李雷", 20));
coll.add(null);
/* boolean contains(Object o):如果此 collection 包含指定的元素,则返回 true。
boolean containsAll(Collection<?> c):如果此 collection 包含指定 collection 中的所有元素,则返回 true。
判断集合中是否存在元素:boolean isEmpty():如果此 collection 不包含元素,则返回 true。
*/
boolean result = coll.contains("abc");
System.out.println(result); //打印结果true
result = coll.contains(new Student("李雷", 20));
System.out.println(result); //打印结果true
Collection coll2 = new ArrayList();
coll2.add(123);
coll2.add(true);
coll2.add(new Student("李雷", 20));
result = coll.containsAll(coll2);
System.out.println(result);//打印结果true
System.out.println(coll.isEmpty());//判断集合中是否存在元素
System.out.println("***********************************");
删除集合元素
//删除
/* 移除交集部分
boolean removeAll(Collection<?> c):移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。 */
boolean result2 = coll.removeAll(coll2);
System.out.println(result2);
System.out.println(coll);
System.out.println(coll2);
/* 保留交集部分
boolean retainAll(Collection<?> c):仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。 */
boolean result3 = coll.retainAll(coll2);
System.out.println(result3);
System.out.println(coll);
System.out.println(coll2);
/*
①删除操作:boolean remove(Object o):从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。
②清空操作:void clear():移除此 collection 中的所有元素(可选操作)。*/
boolean result = coll.remove("abc");
System.out.println(result);
System.out.println(coll + "-->" + coll.size());
coll.clear();
System.out.println(coll + "-->" + coll.size());
}
}
2.2)list接口的独有方法
获取:get方法
// 和index有关
public static void test4() {
List list = new ArrayList(); //多态了
list.add("abc");
list.add(123);
list.add(3.14);
list.add(true);
list.add(new Student("韩梅梅", 19));
System.out.println(list);
/*
获取操作:
E get(int index):返回列表中指定位置的元素。
*/
//使用一般for循环遍历list集合元素
for (int i = 0;i <= list.size() - 1;i++) {
System.out.println(list.get(i));
}
修改:set方法
public static void test3() {
List list = new ArrayList(); //多态了
list.add("abc");
list.add(123);
list.add(3.14);
list.add(true);
list.add(new Student("韩梅梅", 19));
System.out.println(list);
/*
改操作:
E set(int index, E element):用指定元素替换列表中指定位置的元素(可选操作)。
*/
list.set(3, false);
System.out.println(list);
}
删除:remove方法
public static void test2() {
List list = new ArrayList(); //多态了
list.add("abc");
list.add(123);
list.add(3.14);
list.add(true);
list.add(new Student("韩梅梅", 19));
System.out.println(list);
/*
删操作:
E remove(int index):移除列表中指定位置的元素(可选操作)。
boolean remove(Object o):从此列表中移除第一次出现的指定元素(如果存在)(可选操作)。
*/
// Object obj = list.remove(0);
// System.out.println(obj);
// System.out.println(list);
/*
运行时异常:下标越界异常
java.lang.IndexOutOfBoundsException: Index 123 out of bounds for length 5
// Object obj2 = list.remove(123);
*/
boolean b = list.remove(Integer.valueOf(123));
System.out.println(b);
System.out.println(list);
}
增加:add方法和addAll方法
public static void test1() {
List list = new ArrayList(); //多态了
list.add("abc");
list.add(123);
list.add(3.14);
list.add(true);
list.add(new Student("韩梅梅", 19));
System.out.println(list);
/*
增操作:
void add(int index, E element):在列表的指定位置插入指定元素(可选操作)。
boolean addAll(int index, Collection<? extends E> c):将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。
*/
// list.add(2, false);
// System.out.println(list);
List list2 = new ArrayList();
list2.add("def");
list2.add(false);
list2.add(new Student("李雷", 20));
list.addAll(2, list2);
System.out.println(list);
}
}
2.3)Set接口独有的方法
①无特有函数,均来自Collection
②接口特点不可重复,没有下标,不保证存取的顺序,判断是否重复的依据:hashCode、equals
// 利用set集合不存储重复元素的特点将 Collection集合重复的元素去除
public class Exer {
public static void main(String[] args) {
Collection coll = new ArrayList();
coll.add("aaa");
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
coll.add("ccc");
coll.add("bbb");
//创建LinkedHashSet集合容器
LinkedHashSet set = new LinkedHashSet(coll);
System.out.println(set);//打印结果[aaa, bbb, ccc]
//清空coll集合元素
coll.clear();
//将set集合中的元素全部加入到coll集合容器中
coll.addAll(set);//
System.out.println(coll);。
}
}
2.4)使用迭代器Iterator 遍历集合元素
分别使用了Iterator ,增强for,,普通for遍历了集合,最后一个例子使用了list独有的迭代器的previous方法进行了反向遍历。
Collection coll = new ArrayList();
coll.add("aaa");
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
coll.add("ccc");
coll.add("bbb");
//使用iterator方法获得Iterator 对象
Iterator it = coll.iterator();
System.out.println(it.next());//打印结果aaa
System.out.println(it.next());//打印结果aaa
// System.out.println(it.next());写太多了这个,会运行时异常:没有足够元素的异常:java.util.NoSuchElementException
//使用hasNext判断是否有元素 循环遍历coll集合元素
while (it.hasNext()) {
Object next = it.next();
System.out.print(next);//遍历结果
}
//使用增强for遍历coll集合
for (Object obj: coll) {
System.out.print(obj);
}
//因为list集合有get方法,而Collection 接口没有get方法,接口无法使用实现类独有方法,
//所以强转为list集合后使用for循环遍历
System.out.println("");
List lis = (List)coll;
for (int i = 0; i < lis.size(); i++) {
System.out.print(lis.get(i));
}
//使用迭代器遍历list集合
System.out.println("正向遍历:");
ListIterator lit = list.listIterator(); //获取List相关的迭代器对象
while (lit.hasNext()) {
System.out.print(lit.next());
}
//使用迭代器反向遍历list集合
System.out.println("反向遍历:");
while (lit.hasPrevious()) {
System.out.println(lit.previous());
第三章、List集合下的ArrayList和LinkedList
3.1)ArrayList集合
①ArrayList类实现了collection接口、List接口,因此有了collection接口和List接口的方法,本身并没有太特别的方法。
②底层:它的底层使用的可变数组,所以有下标,并且是有序的可以按照数组的方式操作ArrayList集合,因为有下标可以直接通过下标查询,所以查询效率高;
③存取:可以保证数据的存取顺序(第一个元素添加到集合中,那么取出也是第一个取出),同时还可以保存重复元素,也可以存储null元素,因为增加和删除数据的时候其他数据要移动,所以增加和删除效率比较低。
//有独有方法但是没啥常用的独有方法
public class ArrayListDemo {
public static void main(String[] args) {
ArrayList list=new ArrayList();
//向集合中添加数据
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
//遍历集合
for (Iterator it = list.iterator(); it.hasNext();) {
System.out.println(it.next());
}
}
}
3.2)LinkedList集合
①LinkedList类实现了collection接口、List接口,因此有了collection接口和List接口的方法,本身特别方法主要和首位相关。
②底层:使用的链接列表(链表)数据结构。链表结构的特点:有头有尾。
③存取:使用节点来存储数据,实际存储自己的数据+其他节点的地址,而作为链表结构中的最后一个节点的存储地址的空间是null。查询遍历由于链表结构的特点,查询只能从头一直遍历到链表的结尾,所以链表结构查询慢,但增加或者删除只需要在增加或者删除节点的位置上记住新的节点的地址即可,而其他节点不需要移动,所以增删速度会快。
独有方法
方法名 | 解释 |
---|---|
addFirst(E e) | 将指定元素插入此列表的开头 |
addLast(E e) | 将指定元素添加到此列表的结尾 |
getLast() | 返回此列表的最后一个元素 |
getFirst() | 返回此列表的第一个元素 |
removeFirst() | 移除并返回此列表的第一个元素 |
removeLast() | 移除并返回此列表的最后一个元素 |
// 独有方法:主要是首尾方法
public class TestLinkedList {
public static void main(String[] args) {
test();
}
public static void test() {
LinkedList list = new LinkedList();
list.add("abc");
list.add(123);
list.add(3.14);
list.add(true);
list.add(new Student("韩梅梅", 19));
System.out.println(list);
/*增操作:
void addFirst(E e):将指定元素插入此列表的开头
void addLast(E e):将指定元素添加到此列表的结尾 */
list.addFirst(666);
list.addLast(999);
System.out.println(list);
/*获取操作:
E getFirst():返回此列表的第一个元素。
E getLast():返回此列表的最后一个元素。*/
System.out.println(list.getFirst());
System.out.println(list.getLast());
/*删除操作:
E removeFirst():移除并返回此列表的第一个元素。
E removeLast():移除并返回此列表的最后一个元素。*/
list.removeFirst();
list.removeLast();
System.out.println(list);
}
}
3.3)Vector集合
①Vector是jdk1.0出现的集合,它的增删,查询效率都比较低;
②Vector底层使用可变数组结构,是线程安全的。而ArrayList 的底层是不安全的。
③Vector类已经几乎不再使用
public static void main(String[] args) {
Vector v = new Vector();
v.addElement("abc");
v.addElement(123);
v.addElement(3.14);
v.addElement(true);
v.addElement(null);
v.addElement(new Student("李雷", 20));
Iterator it = v.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
第四章、Set集合下的HashSet和LinkedHashSet和TreeSet
4.0)set集合如何比较
①如果hashCode值不一致,则直接存入,如果hashCode是一致的,继续比较equals
②如果equals比较结果为false,则都存入,如果equals比较结果为true,舍弃后者
public class Student {
String name;
int age;
public Student() { }
public Student(String name, int age) {
this.name = name;
this.age = age; }
@Override
public String toString() {
return "{" + name + ", " + age + '}';
}
@Override
public boolean equals(Object o) {
//调用equals方法时会打印这个
System.out.println("equals..");
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
//调用hashCode方法时会打印这个
System.out.println("hashCode.");
return Objects.hash(name, age);
}
}
//-------------------------分割-------------------------
public class TestHashSet {
public static void main(String[] args) {
HashSet set = new HashSet();
set.add(new Student("李雷", 20));//添加时调hashCode打印hashCode被调
set.add(new Student("李雷", 20));//添加时调hashCode和equals,打印hashCode被调equals被调
System.out.println(set);//打印[{李雷, 20}]
System.out.println(new Student("李雷", 20).hashCode());//hashCode被调,哈希值26613644
System.out.println(new Student("李雷", 20).hashCode());//hashCode被调,哈希值26613644
System.out.println(new Student("李雷", 21).hashCode());//hashCode被调,哈希值26613645
}
}
4.1)HashSet集合
①特点:特点:完全无序,且不可以重复,根据计算出现的散列表位置跳跃式的进行存储
②判断是否重复的依据:hashCode、equals
HashSet set = new HashSet();
set.add("赵二");
set.add("张三");
set.add("李四");
set.add("王五");
set.add(1);
System.out.println(set);
//打印结果是无序的[李四, 1, 张三, 赵二, 王五]
//遍历集合
for (Iterator it = set.iterator(); it.hasNext();) {
//输出集合中的数据
System.out.println(it.next()+" ");//李四 1 张三 赵二 王五
}
4.2)LinkedHashSet集合
①特点:有序的,保证元素不可重复的前提下,维护了一层添加顺序
②判断是否重复的依据:hashCode、equals
LinkedHashSet set = new LinkedHashSet();
set.add("张三");
set.add("张三");
set.add("李四");
set.add("王五");
set.add(6);
System.out.println(set);
//添加顺序是存在的[张三, 李四, 王五, 6]
//遍历集合
for (Iterator it = set.iterator(); it.hasNext();) {
//输出集合中的数据
System.out.print(it.next()+" ");//张三 李四 王五 6
}
4.3)TreeSet集合
①无序性,保证元素不可重复的前提下,通过Comparable和Comparator接口维护了一层比较关系(下一章会提到)
②判断元素是否重复的标准:如果两个对象是相等的,则认为它们是重复的
③TreeSet集合内部只能存储相同类型的对象
TreeSet set = new TreeSet();
set.add(789);
set.add(123);
set.add(123);
set.add(456);
set.add(1);
System.out.println(set);//比较顺序[1, 123, 456, 789]
//遍历集合
for (Iterator it = set.iterator(); it.hasNext();) {
//输出集合中的数据
System.out.print(it.next()+" ");//遍历结果1 123 456 789
}
4.4)从TreeSet讲到Comparable和Comparator接口
重点:Comparable位于包java.lang下而Comparator接口位于包java.util下,都可以用来实现集合中元素的比较、排序,Comparable接口将比较代码放在自身类中,而Comparator可以在自身类中,也可以在一个独立的类中实现比较。
①使用空参构造方法创建TreeSet集合容器,则存储的对象类型都必须实现了Comparable接口
// 自定义类Employee对象存入到TreeSet容器中 ==> 此类实现Comparable接口
public class Employee implements Comparable<Employee>{
int id;
int age;
public Employee() { }
public Employee(int id, int age) {
this.id = id;
this.age = age; }
@Override
public String toString() {
return "Employee{" +"id=" + id +", age=" + age +'}';
}
@Override
public int compareTo(Employee e) {
//升序
return this.age - e.age; }
}
//-------------------------------------------------
// 使用空参构造方法创建TreeSet集合容器,则存储的对象类型都必须实现了Comparable接口
TreeSet set = new TreeSet();
set.add(new Employee(1, 30));
set.add(new Employee(2, 22));
set.add(new Employee(3, 36));
System.out.println(set);
//比较age打印结果升序[Employee{id=2, age=22}, Employee{id=1, age=30}, Employee{id=3, age=36}]
②使用带参构造方法创建TreeSet集合容器,参数位置传入一个Comparator接口的实现类对象即可
//圆类
public class Circle {
private double radius;
public Circle(double radius) {
this.radius = radius; }
public Circle() { }
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
@Override
public String toString() {
return "{" + radius +
'}';
}
}
//------------------------------------------------
//半径比较器类
public class RadiusComparator implements Comparator<Circle> {
@Override
public int compare(Circle c1, Circle c2) {
//降序
return (int) (c2.getRadius() - c1.getRadius());
}
}
//------------------------------------------------
//自定义类Circle对象存入到TreeSet容器中 ==> 使用带参构造创建TreeSet容器对象,参数位置传入一个Comparator接口的实现类对象即可
TreeSet set = new TreeSet(new RadiusComparator());
set.add(new Circle(4.0));
set.add(new Circle(6.0));
set.add(new Circle(1.0));
set.add(new Circle(5.0));
set.add(new Circle(2.0));
set.add(new Circle(3.0));
System.out.println(set);
//打印结果[{6.0}, {5.0}, {4.0}, {3.0}, {2.0}, {1.0}]