Java_集合框架

发布时间 2023-11-17 15:01:32作者: Espre-sso

Java集合的总体系

分类:
Collection接口,Map接口
Collection接口:List接口,Set接口
Map接口:

Collection集合体系

子接口:
接口List:元素有序,可重复,有索引
实现类:ArrayList、LinkedList
接口Set:元素无序,不重复,无索引
实现类:HashSet、LinkedHashSet(有序)、TreeSet(默认升序)

Collection接口的通用方法

方法汇总:
addaddAllclearisEmptysizecontainsremovetoArray(默认Object数组接收)、toArray(new int[c.size()])(这样就可以用int数组接收了)

Collection的遍历方式

分类:

  1. Iterator迭代器:
点击查看代码
Iterator<String> it =  c.iterator();
while(it.hasNext()){
  String s = it.next();
  System.out.println(s);
}
  1. 增强for循环:for(String s:c)可以遍历集合、数组,是迭代器的简化写法
  2. Lambda表达式:(jdk1.8之后)
点击查看代码
c.forEach(s->{
System.out.println(s);
});

没有fori,因为不支持下标访问无索引

List系列集合的常用方法

add(index,ele),remove(index),set(index,ele),get(index)
遍历方法:
比Collection多了一种 fori遍历(因为支持索引)

ArrayList的扩容原理

过程:

  1. 利用无参构造器创建的集合,会在底层创建一个默认长度为0的数组
  2. 添加第1个元素时,会在底层创建一个新的长度为10的数组
  3. 存满时,会扩容1.5倍
  4. 如果一次添加多个元素list1.addAll(list2),1.5倍放不下,则新创建数组的长度以实际为准。

LinkedList类的常用方法

addFirst也可以用push,addLast,getFirst,getLast,removeFirst也可以用pop,removeLast
增加这么多首尾操作的原因:
LinkedList底层是双向链表,对首尾的操作速度极快。

LinkedList的应用场景

  1. 设计队列-先进先出
  2. 设计栈-后进先出

Set系列集合

特点:
不重复,无索引
分类:
HashSet 无序,LinkedHashSet 有序,TreeSet 排序
常用方法:
基本都是父类Collection提供的,自己没有额外新增一些常用功能。

HashSet底层原理

JDK8之前:

  1. 创建一个默认长度为16的数组,默认加载因子0.75,数组名table。
  2. 使用元素的哈希值对数组的长度求余,计算出应存入的位置。
  3. 当前位置如果是null,则直接存入。如果不为null,调用equals方法比较,相等,不存,不相等,存入数组。(JDK8之前,老元素挂新元素下面。JDK8之后,新元素挂老元素下面)

JDK8之后:
当链表长度超过8,且数组长度>=64时,自动将链表转化成红黑树(平衡二叉树)。

HashSet去重

如果希望set集合认为两个内容一样的对象是重复的,必须重写对象的hashCode()和equals()方法

LinkedHashSet底层原理

底层数据结构:
依然是基于哈希表(数组+链表+红黑树)实现的。
但是,它的每一个元素额外多了一个双链表机制记录它前后元素的位置。同时还有两个指针,指向首尾元素。

TreeSet底层原理

底层数据结构:
底层是基于红黑树实现的排序。
注意事项:

  1. 对于数值类型Integer,Double,默认按照数值本身大小进行升序排列。
  2. 对于字符串类型,按照首字符的编号升序排序。
  3. 对于自定义类型Student,TreeSet默认无法直接排序。

如何实现对自定义类型的排序:

  1. 自定义类Student实现Comparable接口,重写里面的CompareTo方法来指定比较规则。
  2. 通过调用TreeSet有参构造器,可以设置Comparator对象(比较器对象,用于指定比较规则)。
  3. 如果同时使用了两种方法,就近原则-默认使用集合自带的比较器排序

集合的并发修改异常

  1. 使用迭代器Iterator遍历集合,同时删除集合中的数据,要用迭代器自己的删除方法it.remove(),底层是通过迭代器--实现的安全删除。
  2. 使用fori遍历集合,可以使用倒序删除,或者在删除时i--。
  3. 增强for循环,底层用的Iterator。Lambda表达式,底层用的增强for循环。这两种情况是无法解决集合的遍历并发修改异常的。

可变参数

定义:
数据类型...参数名称
特点:
可以传0、1、多个数据给它,也可以传数组给它。
注意事项:

  1. 可变参数在方法内部是一个数组。
  2. 一个形参列表中可变参数只能有一个。
  3. 可变参数必须放在形参列表的最后。

Collections工具类

常用的静态方法:
addAll,shuffle,sort(list),sort(list,Comparator)
用法:
Collections.sort(list);

Map集合体系

特点:
不重复,无索引
分类:
HashMap 无序,LinkedHashMap 有序,TreeMap 排序。

Map集合常用方法

put(key,value),size,clear,isEmpty,get,remove,containsKey,containsValue,keySet,values,putAll

Map集合的遍历方式

  1. 键找值(先获取Map集合所有的键,再通过遍历键来找值)
点击查看代码
Set<String> keys = map.keySet();
for(String key :keys){
  ...;
}
  1. 键值对(把键值对看成一个整体遍历-难度较大)
点击查看代码
Set<Map.Entry<String,Double>> entries = map.entrySet();
for(Map.Entry<String,Double>> entry :entries){
  ...;
  entry.getKey();
  entry.getValue();
}
  1. Lambda(JDK1.8开始的新技术-很简单)
    底层用到的是2.键值对遍历
点击查看代码
map.forEach( (k,v)->{
  System.out.println(k+"-->"+v);
});

Map集合的使用场景

场景:
需要存储一一对应的数据时。

Map底层原理

底层数据结构:
map与set一样,set底层也用的map

内部类

分类:

  1. 成员内部类:Outer.Inner in = new Outer().new Inner();
    在成员中定义的类
  2. 静态内部类:Outer.Inner in = new Outer.Inner();
    在成员中定义的static修饰的类
  3. 局部内部类:在方法、代码块中定义的类(没啥用)
  4. 匿名内部类:
点击查看代码
new 接口(参数值){
  类体(一般是方法重写);
};

用法:
匿名内部类本质是一个子类,并会立即创建出一个子类对象。通常作为一个参数传给方法。

JDK8新特性:Lambda表达式

作用:
用于简化匿名内部类
格式:

点击查看代码
(被重写的形参列表)->{
  被重写方法的方法体代码;
}

注意:
Lambda表达式只能简化函数式接口的匿名内部类(有且仅有一个抽象方法的接口,@FUnctionalInterface注解)
省略规则:

  1. 参数类型可以省略不写
  2. 如果只有一个参数()也可以省略
  3. 如果方法体只有一行代码,可以省略 {}和;同时return也可以省略。

JDK8新特性:方法引用

标志性符号:
::
分类:

  1. 静态方法的引用
  2. 实例方法的引用
  3. 特定类型方法的引用
  4. 构造器引用
    注意:
    方法引用只是一种简化代码的方式,在开发中不要刻意去简化。

随机数

点击查看代码
Random r = new Random();
int index  = r.nextInt(4);//生成int类型的随机数,范围0,1,2,3