集合
集合和数组都是容器
数组的特点:
数组定义完成并启动后,类型确定、长度固定
适合元素的个数和类型确定的业务场景,不适合做需要增删数据操作
集合的特点:
集合的大小不固定,启动后可以动态变化,类型也可以选择不固定
集合非常适合做元素的增删操作
1.数组和集合的元素存储的个数
数组定义后类型确定,长度固定
集合类型可以不固定,大小是可变的
2.数组和集合存储元素的类型问题
数组可以存储基本类型和引用类型的数据
集合只能存储引用数据类型的数据
3.数组和集合适合的场景
数组适合做数据个数和类型确定的场景
集合适合做数据个数不确定,且要做增删元素的场景
集合类体系结构
🐼Collection:单列集合,每个元素包含一个值
🐼Map: 双列集合,每个元素包含两个值(键值对)
Collection集合体系
Collection集合特点:
List系列集合:添加的元素是有序、可重复、有索引
ArrayList:有序、可重复、有索引LinekdList :有序、可重复、有索引
Set系列集合:添加的元素是无序、不重复、无索引
HashSet: 无序、不重复、无索引LinkedHashSet: 有序、不重复、无索引
TreeSet:按照大小默认升序排序、不重复、无索引集合对于泛型的支持:
集合都是支持泛型的,可以在编译阶段约束集合只能操作某种数据类型
Collection<String> lists = new ArrayList<String>(); Collection<String> lists = new ArrayList<>(); // JDK 1.7开始后面的泛型类型申明可以省略不写
集合中要存储基本类型的数据,就要使用包装类
// 存储基本类型使用包装类 Collection<Integer> lists = new ArrayList<>(); Collection<Double> lists = new ArrayList<>();
1.集合的代表是?
Collection接口2.Collection集合分了哪2大常用的集合体系?
List系列集合:添加的元素是有序、可重复、有索引
Set系列集合:添加的元素是无序、不重复、无索引3.如何约定集合存储数据的类型,需要注意什么?
集合支持泛型
集合和泛型不支持基本类型,只支持引用数据类型
Collection集合常用API
Collection是单列集合的祖宗接口,它的功能是全部单列集合都可以继承使用的
Collection集合常用API:
Collection集合的遍历方式
方式一:迭代器
遍历就是一个一个的把容器中的元素访问一遍
迭代器在Java中的代表是Iterator,迭代器是集合的专用遍历方式Collection集合获取迭代器
Iterator中的常用方法
迭代器执行流程
Iterator<String> it = lists.iterator(); while(it.hasNext()){ String ele = it.next(); System.out.println(ele); }
1.迭代器的默认位置在哪里?
Iterator<E> iterator():得到迭代器对象,默认指向当前集合的索引02.迭代器如果取元素越界会出现什么问题?
会出现NoSuchElementException异常
方式二:增强for循环
既可以遍历集合也可以遍历数组
格式:
for(元素数据类型 变量名 : 数组或者Collection集合) {
//在此处使用变量即可,该变量就是元素
}
例:
Collection<String> list = new ArrayList<>(); for(String ele : list) { System.out.println(ele); }
注:
修改第三方变量的值不会影响到集合中的元素1.增强for可以遍历哪些容器?
既可以遍历集合也可以遍历数组
方式三:lambda表达式
JDK 8开始的新技术Lambda表达式,提供了一种更简单、更直接的遍历集合的方式
Collection结合Lambda遍历的API
Collection<String> lists = new ArrayList<>(); lists.forEach(new Consumer<String>() { @Override public void accept(String s) { System.out.println(s); } });
lists.forEach(s -> { System.out.println(s); }); //lists.forEach(s -> System.out.println(s));
Collection集合存储自定义类型的对象
需求:
某影院系统需要在后台存储上述三部电影,然后依次展示出来
分析:
定义一个电影类,定义一个集合存储电影对象
创建3个电影对象,封装相关数据,把3个对象存入到集合中去
遍历集合中的3个对象,输出相关信息public class Movie { private String name; private double score; private String actor; // 主演 public Movie() { } public Movie(String name, double score, String actor) { this.name = name; this.score = score; this.actor = actor; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getScore() { return score; } public void setScore(double score) { this.score = score; } public String getActor() { return actor; } public void setActor(String actor) { this.actor = actor; } @Override public String toString() { return "Movie{" + "name='" + name + '\'' + ", score=" + score + ", actor='" + actor + '\'' + '}'; } }
import java.util.ArrayList; import java.util.Collection; public class TestDemo { public static void main(String[] args) { // 1、定义一个电影类 // 2、定义一个集合对象存储3部电影对象 Collection<Movie> movies = new ArrayList<>(); movies.add(new Movie("《你好,李焕英》", 9.5, "张小斐,贾玲,沈腾,陈赫")); movies.add(new Movie("《唐人街探案》", 8.5, "王宝强,刘昊然,美女")); movies.add(new Movie("《刺杀小说家》",8.6, "雷佳音,杨幂")); System.out.println(movies); // 3、遍历一下这三个电影对象 for (Movie movie : movies) { System.out.println(movie.getName()); System.out.println(movie.getActor()); System.out.println(movie.getScore()); System.out.println("-------------------"); } } }
1.集合中存储的是元素的什么信息?
集合中存储的是元素对象的地址
List系列集合
List系列集合特点和特有API
List系列集合特点:
ArrayList LinekdList :有序,可重复,有索引。
有序:存储和取出的元素顺序一致
有索引:可以通过索引操作元素
可重复:存储的元素可以重复List集合特有方法
List集合因为支持索引,所以多了很多索引操作的独特API,其他Collection的功能List也都继承了
1.List系列集合特点
ArrayList LinekdList :有序,可重复,有索引
2.List的实现类的底层原理
ArrayList 底层是基于数组实现的,根据索引查询元素快,增删相对慢
LinkedList 底层基于双链表实现的,查询元素慢,增删首尾元素是非常快的
List集合的遍历方式小结
方式一:迭代器
方式二:增强for循环
方式三:Lambda表达式
方式四:or循环(因为List集合存在索引)import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** 拓展:List系列集合的遍历方式有:4种。 List系列集合多了索引,所以多了一种按照索引遍历集合的for循环。 List遍历方式: (1)for循环。(独有的,因为List有索引)。 (2)迭代器。 (3)foreach。 (4)JDK 1.8新技术。 */ public class ListDemo { public static void main(String[] args) { ArrayList<String> lists = new ArrayList<>(); lists.add("java1"); lists.add("java2"); lists.add("java3"); /** (1)for循环。 */ System.out.println("-----------------------"); for (int i = 0; i < lists.size(); i++) { String ele = lists.get(i); System.out.println(ele); } /** (2)迭代器。 */ System.out.println("-----------------------"); Iterator<String> it = lists.iterator(); while (it.hasNext()){ String ele = it.next(); System.out.println(ele); } /** (3)foreach */ System.out.println("-----------------------"); for (String ele : lists) { System.out.println(ele); } /** (4)JDK 1.8开始之后的Lambda表达式 */ System.out.println("-----------------------"); lists.forEach(s -> { System.out.println(s); }); } }
ArrayList集合
ArrayList集合支持索引
ArrayList集合的对象的创建
ArrayList集合的添加元素的方法
泛型:
ArrayList<E>:其实就是一个泛型类,可以在编译阶段约束集合对象只能操作某种数据类型
例:
ArrayList<String> :此集合只能操作字符串类型的元素。
ArrayList<Integer>:此集合只能操作整数类型的元素注:泛型只能支持引用数据类型,不支持基本数据类型
ArrayList集合常用方法
ArrayList集合底层原理
ArrayList底层是基于数组实现的:根据索引定位元素快,增删需要做元素的移位操作
第一次创建集合并添加第一个元素的时候,在底层创建一个默认长度为10的数组List<String> list = new ArrayList<>(); list.add("a");
List集合存储的元素要超过容量:继续生成长度为10的数组
LinkedList集合
底层数据结构是双链表,查询慢,首尾操作的速度是极快的,所以多了很多首尾操作的特有API
LinkedList集合的特有功能
LinkedList集合底层原理
集合的并发修改异常问题
哪些遍历存在问题?
迭代器遍历集合且直接用集合删除元素的时候可能出现。
增强for循环遍历集合且直接用集合删除元素的时候可能出现
哪种遍历且删除元素不出问题?迭代器遍历集合但是用迭代器自己的删除方法操作可以解决。
使用for循环遍历并删除元素不会存在这个问题
集合工具类Collections
Collections集合工具类
java.utils.Collections
作用:Collections并不属于集合,是用来操作集合的工具类
Collections常用的API
Collections排序相关API
只能对于List集合的排序
排序方式1:
排序方式2:
Set系列集合
Set系列集合特点和特有API
Set系列集合特点:
无序:存取顺序不一致
不重复:可以去除重复
无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素Set集合实现类特点
HashSet:无序、不重复、无索引
LinkedHashSet:有序、不重复、无索引
TreeSet:排序、不重复、无索引Set集合的功能上基本上与Collection的API一致
实现类HashSet集合
底层采取哈希表存储的数据
性能:哈希表是一种对于增删改查数据性能都较好的结构
哈希表的组成
JDK8之前的,底层使用数组+链表组成
JDK8开始后,底层采用数组+链表+红黑树组成哈希值
是JDK根据对象的地址,按照某种规则算出来的int类型的数值
Object类的API
public int hashCode():返回对象的哈希值
对象的哈希值特点
同一个对象多次调用hashCode()方法返回的哈希值是相同的
默认情况下,不同对象的哈希值是不同的
HashSet1.7
HashSet1.8
HashSet去重复
实现类LinkedHashSet集合
有序 不重复 无索引
有序:
这里的有序指的是保证存储和取出的元素顺序一致
原理:
底层数据结构是依然哈希表,只是每个元素之间用的是一个双链表的机制记录存储的顺序
实现类TreeSet集合
可排序 不重复 无索引
可排序:
按照元素的大小默认升序(有小到大)排序
性能:
TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好
注意:
TreeSet集合是一定要排序的,可以将元素按照指定的规则进行排序
TreeSet集合默认的规则:
对于数值类型:Integer , Double,官方默认按照大小进行升序排序
对于字符串类型:默认按照首字符的编号升序排序
对于自定义类型:如Student对象,TreeSet无法直接排序自定义排序规则:
方式一:
让自定义的类(如学生类)实现Comparable接口重写里面的compareTo方法来定制比较规则
方式二:TreeSet集合有参数构造器,可以设置Comparator接口对应的比较器对象,来定制比较规则
两种方式中,关于返回值的规则:
如果认为第一个元素大于第二个元素返回正整数即可 值1>值2: 1
如果认为第一个元素小于第二个元素返回负整数即可 值1<值2:-1
如果认为第一个元素等于第二个元素返回0即可,此时Treeset集合只会保留一个元素,认为两者重复 值1=值2:0
注意:如果TreeSet集合存储的对象有实现比较规则,集合也自带比较器,默认使用集合自带的比较器排序
Collection体系的特点、使用场景总结
1. 如果希望元素可以重复,又有索引,索引查询要快?
用ArrayList集合,基于数组的(用的最多)
2. 如果希望元素可以重复,又有索引,增删首尾操作快?
用LinkedList集合,基于链表的
3. 如果希望增删改查都快,但是元素不重复、无序、无索引?
用HashSet集合,基于哈希表的
4. 如果希望增删改查都快,但是元素不重复、有序、无索引?
用LinkedHashSet集合,基于哈希表和双链表
5. 如果要对对象进行排序?
用TreeSet集合,基于红黑树,后续也可以用List集合实现排序