目录
一、为什么要引用集合类?
数组的特点:
集合的特点:
二、集合类体系结构:
三、Collection集合体系:
四、Collection常用API:
五、遍历方式:
迭代器:
foreach/增强for循环:
Lambda表达式:
六、List系列集合:
List系列集合特点:
List集合特有方法:
ArrayList集合底层原理:
LinkedList的特点:
LinkedList集合特有功能:
七、Set系列集合:
Set系列集合特点:
Set集合实现类特点:
HashSet元素无序、去重复的底层原理:哈希表
LinkedHashSet集合概述和特点:
TreeSet集合概述和特点:
TreeSet集合默认的规则:
自定义排序规则:
八、总结:
一、为什么要引用集合类?
提到集合类都会想到数组,集合和数组都是容器。
数组的特点:
1、数组的类型确定,长度固定。
2、在进行增删该改查操作时,需要放弃原有数组或者移位,所以数组不太适合。
集合的特点:
1、集合的大小不固定,可以动态变化,类型也可以选择不固定。
2、集合非常适合元素的增删改查。
注意:集合只能存储引用类数据,如果想要存储基本数据类型可以选用包装类。
二、集合类体系结构:
- Collection单列集合:每个元素(数据)只包含一个值。
- Map双列集合:每个元素包含两个值。
注意:今天先总结Collection系列集合。
三、Collection集合体系:
四、Collection常用API:
package com.jiazhong.Aggregate.Collection.Collection_api;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
/*
*/
public class Collection_api {
public static void main(String[] args) {
Collection<String> list = new ArrayList<>();
//1、添加元素,添加成功返回true
list.add("Java");
list.add("Java");
list.add("HTML");
System.out.println(list.add("MySQL"));
list.add("Python");
System.out.println(list);
//2、清空集合的元素
// list.clear();
// System.out.println(list);
//3、判断集合是否为空,空返回true,反之false
// System.out.println(list.isEmpty());
//4、获取集合的大小
System.out.println(list.size());
//5、判断集合中是否包含某个元素
System.out.println(list.contains("Java"));
System.out.println(list.contains("java"));
//6、删除某个元素:如果有多个重复元素默认删除第一个
list.remove("Java");
System.out.println(list);
//7、把集合转换成数组
Object[] o = list.toArray();
System.out.println("数组:"+ Arrays.toString(o));
System.out.println("---------拓展---------");
Collection<String> c1 = new ArrayList<>();
c1.add("java");
c1.add("Java");
Collection<String> c2 = new ArrayList<>();
c2.add("张三");
c2.add("你好");
c2.addAll(c1);
System.out.println(c1);
System.out.println(c2);
}
}
五、遍历方式:
迭代器:
package com.jiazhong.Aggregate.Collection.Collection_traversal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/*
迭代器
*/
public class CollectionDemo01 {
public static void main(String[] args) {
Collection<String> list = new ArrayList<>();
list.add("杨港");
list.add("张三");
list.add("李四");
list.add("王五");
System.out.println(list);
//1、得到当前集合的迭代器对象
Iterator<String> it = list.iterator();
// String e = it.next();
// System.out.println(e);
// System.out.println(it.next());
// System.out.println(it.next());
// System.out.println(it.next());
// System.out.println(it.next());//NoSuchElementException
//2、定义while循环
while (it.hasNext()){
String e = it.next();
System.out.println(e);
}
}
}
foreach/增强for循环:
package com.jiazhong.Aggregate.Collection.Collection_traversal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
/*
foreach/增强for循环
*/
public class CollectionDemo02 {
public static void main(String[] args) {
Collection<String> list = new ArrayList<>();
list.add("杨港");
list.add("张三");
list.add("李四");
list.add("王五");
for (String s : list) {
System.out.println(s);
}
double[] score = {11.1,45.5,60.5,59.5};
for (double ele : score) {
System.out.println(ele);
}
}
}
Lambda表达式:
package com.jiazhong.Aggregate.Collection.Collection_traversal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Consumer;
/*
Lambda表达式
*/
public class CollectionDemo03 {
public static void main(String[] args) {
Collection<String> list = new ArrayList<>();
list.add("杨港");
list.add("张三");
list.add("李四");
list.add("王五");
// list.forEach(new Consumer<String>() {
// @Override
// public void accept(String s) {
// System.out.println(s);
// }
// });
list.forEach( s-> {
System.out.println(s);
});
}
}
六、List系列集合:
List系列集合特点:
- ArrayList、LinkedList : 有序、可重复、有索引。
- 有序:存储和取出的元素顺序一致。
- 可重复:存储的元素可以重复。
- 有索引:可以通过索引操作元素。
List集合特有方法:
package com.jiazhong.Aggregate.Collection.Collection_list;
import java.util.ArrayList;
import java.util.List;
public class ListDemo01 {
public static void main(String[] args) {
// 1.创建一个ArrayList集合对象:
// List:有序,可重复,有索引的。
List<String> list = new ArrayList<>();
list.add("Java");
list.add("Java");
list.add("Html");
list.add("Web");
// 2.在某个索引位置插入元素。
list.add(2,"你好");
System.out.println(list);
// 3.根据索引删除元素,返回被删除元素
System.out.println(list.remove(2));
System.out.println(list);
// 4.根据索引获取元素:public E get(int index):返回集合中指定位置的元素。
System.out.println(list.get(2));
// 5.修改索引位置处的元素: public E set(int index, E element)
System.out.println(list.set(1, "高斯林"));
System.out.println(list);
}
}
ArrayList集合底层原理:
ArrayList底层是基于数组实现的:根据索引定位元素快,增删需要做元素的移位操作。
第一次创建集合并添加第一个元素时,在底层创建一个默认长度为10的数组。
LinkedList的特点:
底层数据结构是双链表,查询慢,首尾操作速度是极快的,所以有很多首尾特有的API。
LinkedList集合特有功能:
package com.jiazhong.Aggregate.Collection.Collection_list;
import java.util.LinkedList;
public class ListDemo03 {
public static void main(String[] args) {
//LinkedList 可以完成队列结构,和栈结构(双向链表)
//栈
LinkedList<String> stack = new LinkedList<>();
//压栈 入栈
stack.push("第一颗子弹");
stack.addFirst("第二颗子弹");
stack.addFirst("第三颗子弹");
stack.addFirst("第四颗子弹");
//出栈 弹栈
stack.pop();
stack.removeFirst();
stack.removeFirst();
System.out.println(stack);
//队列
LinkedList<String> queue = new LinkedList<>();
//入队
queue.addLast("1号");
queue.addLast("2号");
queue.addLast("3号");
queue.addLast("4号");
System.out.println(queue);
queue.removeFirst();
queue.removeFirst();
queue.removeFirst();
System.out.println(queue);
}
}
七、Set系列集合:
Set系列集合特点:
- 无序:存取顺序不一致
- 不重复:可以去除重复
- 无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元 素。
Set集合实现类特点:
- HashSet:无序、不重复、无索引
- LinkedHashSet: 有序、不重复、无索引
- TreeSet:排序、不重复、无索引
Set集合的功能基本上与Collection的API一致。
package com.itheima.d1_set;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
public class SetDemo1 {
public static void main(String[] args) {
Set<String> sets = new HashSet<>();//无序,不重复,无索引
sets.add("MySQL");
sets.add("Java");
sets.add("Java");
sets.add("HTML");
sets.add("HTML");
sets.add("StringBoot");
System.out.println(sets);
Set<String> set = new LinkedHashSet<>();//有序,不重复,无索引
set.add("MySQL");
set.add("Java");
set.add("Java");
set.add("HTML");
set.add("HTML");
set.add("StringBoot");
System.out.println(set);
Set<Integer> sett = new TreeSet<>();//排序,不重复,无索引
sett.add(23);
sett.add(11);
sett.add(5);
sett.add(24);
sett.add(31);
sett.add(10);
System.out.println(sett);
}
}
结果:[Java, StringBoot, MySQL, HTML]
[MySQL, Java, HTML, StringBoot]
[5, 10, 11, 23, 24, 31]
HashSet元素无序、去重复的底层原理:哈希表
哈希表的组成:JDK8之前使用数组+链表组成
JDK8开始采用数组+链表+红黑树组成
对象的哈希值特点:同一对象多次调用hashCode()方法返回的哈希值是相同的。
默认情况下,不同对象的哈希值是不同的。
哈希表的详细流程:
1、创建一个默认长度为16,默认加载0.75的数组
2、根据元素的哈希值和数组的长度求出应存入的位置(哈希值/16的余数即位置)
3、判断当前位置是否为null,不为null直接存入。若为null表示该位置有元素,则调用equals方法比较属性值
4、当数组存满到16*0.75=12时,则扩容,扩容到原来的两倍
LinkedHashSet集合概述和特点:
有序、不重复、无索引
这里的有序指的是保证存储和取出的元素顺序一致
原理:底层数据结构依然是哈希表,只不过每个元素又额外多了一个双链表的机制记录存储的顺序。
TreeSet集合概述和特点:
可排序、不重复、无索引
可排序:按照元素的大小默认升序(由小到大)排序。
TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好。
TreeSet集合默认的规则:
对于数值类型:按照大小进行升序排序。
对于字符串类型:默认按照首字母的编号升序排序。
对于自定义的Student对象,无法直接排序。
结论:想要使用TreeSet存储自定义类型,需要指定排序规则。
自定义排序规则:
Comparable接口重写里面的compareTo方法来制定比较规则。
package com.itheima.d1_set;
public class Student implements Comparable<Student>{
private String name;
private int age;
private char sex;
public Student() {
}
public Student(String name, int age, char sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public char getSex() {
return sex;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSex(char sex) {
this.sex = sex;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (age != student.age) return false;
if (sex != student.sex) return false;
return name != null ? name.equals(student.name) : student.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
result = 31 * result + (int) sex;
return result;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
'}';
}
/*
方法一:实现Comparable接口重写里面的compareTo方法来制定比较规则。
*/
@Override
public int compareTo(Student student) {
return this.age-student.age;
}
}
package com.itheima.d1_set;
import java.util.Set;
import java.util.TreeSet;
public class SetDemo5 {
public static void main(String[] args) {
Set<Student> s = new TreeSet<>();
s.add(new Student("杨港",21,'男'));
s.add(new Student("张三",20,'女'));
s.add(new Student("李四",25,'男'));
System.out.println(s);
}
}
结果:[Student{name='张三', age=20, sex=女}, Student{name='杨港', age=21, sex=男}, Student{name='李四', age=25, sex=男}]
TreeSet集合有参构造器,可以设置Comparator接口对应的比较器对象,来制定比较规则。
package com.itheima.d1_set;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
public class SetDemo6 {
public static void main(String[] args) {
Set<Student> s = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student student, Student t1) {
return t1.getAge()-student.getAge();
}
});
s.add(new Student("杨港", 21, '男'));
s.add(new Student("张三", 20, '女'));
s.add(new Student("李四", 25, '男'));
System.out.println(s);
}
}
结果:[Student{name='李四', age=25, sex=男}, Student{name='杨港', age=21, sex=男}, Student{name='张三', age=20, sex=女}]
八、总结:
1、如果希望元素可以重复,又有索引,索引查询要快。
用ArrayList集合,基于数组的。
2、如果希望元素可以重复,又有索引,增删首尾要快。
用LinkedList集合,基于链表的。
3、如果希望元素增删改查都快,但元素不重复、无序、无索引。
用HashSet集合,基于哈希表的。
4、如果希望元素增删改查都快,但元素不重复、有序、无索引。
用LinkedHashSet集合,基于哈希表和双链表。
5、如果要对希望元素排序。
用TreeSet集合,基于红黑树。