Java集合的总体系
分类:
Collection接口,Map接口
Collection接口:List接口,Set接口
Map接口:
Collection集合体系
子接口:
接口List:元素有序,可重复,有索引
实现类:ArrayList、LinkedList
接口Set:元素无序,不重复,无索引
实现类:HashSet、LinkedHashSet(有序)、TreeSet(默认升序)
Collection接口的通用方法
方法汇总:
add、addAll、clear、isEmpty、size、contains、remove、toArray(默认Object数组接收)、toArray(new int[c.size()])(这样就可以用int数组接收了)
Collection的遍历方式
分类:
- Iterator迭代器:
点击查看代码
Iterator<String> it = c.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
- 增强for循环:
for(String s:c)可以遍历集合、数组,是迭代器的简化写法 - 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的扩容原理
过程:
- 利用无参构造器创建的集合,会在底层创建一个默认长度为0的数组
- 添加第1个元素时,会在底层创建一个新的长度为10的数组
- 存满时,会扩容1.5倍
- 如果一次添加多个元素
list1.addAll(list2),1.5倍放不下,则新创建数组的长度以实际为准。
LinkedList类的常用方法
addFirst也可以用push,addLast,getFirst,getLast,removeFirst也可以用pop,removeLast
增加这么多首尾操作的原因:
LinkedList底层是双向链表,对首尾的操作速度极快。
LinkedList的应用场景
- 设计队列-先进先出
- 设计栈-后进先出
Set系列集合
特点:
不重复,无索引
分类:
HashSet 无序,LinkedHashSet 有序,TreeSet 排序
常用方法:
基本都是父类Collection提供的,自己没有额外新增一些常用功能。
HashSet底层原理
JDK8之前:
- 创建一个默认长度为16的数组,默认加载因子0.75,数组名table。
- 使用元素的哈希值对数组的长度求余,计算出应存入的位置。
- 当前位置如果是null,则直接存入。如果不为null,调用equals方法比较,相等,不存,不相等,存入数组。(JDK8之前,老元素挂新元素下面。JDK8之后,新元素挂老元素下面)
JDK8之后:
当链表长度超过8,且数组长度>=64时,自动将链表转化成红黑树(平衡二叉树)。
HashSet去重
如果希望set集合认为两个内容一样的对象是重复的,必须重写对象的hashCode()和equals()方法
LinkedHashSet底层原理
底层数据结构:
依然是基于哈希表(数组+链表+红黑树)实现的。
但是,它的每一个元素额外多了一个双链表机制记录它前后元素的位置。同时还有两个指针,指向首尾元素。
TreeSet底层原理
底层数据结构:
底层是基于红黑树实现的排序。
注意事项:
- 对于数值类型Integer,Double,默认按照数值本身大小进行升序排列。
- 对于字符串类型,按照首字符的编号升序排序。
- 对于自定义类型Student,TreeSet默认无法直接排序。
如何实现对自定义类型的排序:
- 让自定义类Student实现Comparable接口,重写里面的CompareTo方法来指定比较规则。
- 通过调用TreeSet有参构造器,可以设置Comparator对象(比较器对象,用于指定比较规则)。
- 如果同时使用了两种方法,就近原则-默认使用集合自带的比较器排序。
集合的并发修改异常
- 使用迭代器Iterator遍历集合,同时删除集合中的数据,要用迭代器自己的删除方法
it.remove(),底层是通过迭代器--实现的安全删除。 - 使用fori遍历集合,可以使用倒序删除,或者在删除时i--。
- 增强for循环,底层用的Iterator。Lambda表达式,底层用的增强for循环。这两种情况是无法解决集合的遍历并发修改异常的。
可变参数
定义:
数据类型...参数名称
特点:
可以传0、1、多个数据给它,也可以传数组给它。
注意事项:
- 可变参数在方法内部是一个数组。
- 一个形参列表中可变参数只能有一个。
- 可变参数必须放在形参列表的最后。
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集合的遍历方式
- 键找值(先获取Map集合所有的键,再通过遍历键来找值)
点击查看代码
Set<String> keys = map.keySet();
for(String key :keys){
...;
}
- 键值对(把键值对看成一个整体遍历-难度较大)
点击查看代码
Set<Map.Entry<String,Double>> entries = map.entrySet();
for(Map.Entry<String,Double>> entry :entries){
...;
entry.getKey();
entry.getValue();
}
- Lambda(JDK1.8开始的新技术-很简单)
底层用到的是2.键值对遍历
点击查看代码
map.forEach( (k,v)->{
System.out.println(k+"-->"+v);
});
Map集合的使用场景
场景:
需要存储一一对应的数据时。
Map底层原理
底层数据结构:
map与set一样,set底层也用的map
内部类
分类:
- 成员内部类:
Outer.Inner in = new Outer().new Inner();
在成员中定义的类 - 静态内部类:
Outer.Inner in = new Outer.Inner();
在成员中定义的static修饰的类 - 局部内部类:在方法、代码块中定义的类(没啥用)
- 匿名内部类:
点击查看代码
new 接口(参数值){
类体(一般是方法重写);
};
用法:
匿名内部类本质是一个子类,并会立即创建出一个子类对象。通常作为一个参数传给方法。
JDK8新特性:Lambda表达式
作用:
用于简化匿名内部类
格式:
点击查看代码
(被重写的形参列表)->{
被重写方法的方法体代码;
}
注意:
Lambda表达式只能简化函数式接口的匿名内部类(有且仅有一个抽象方法的接口,@FUnctionalInterface注解)
省略规则:
- 参数类型可以省略不写
- 如果只有一个参数
()也可以省略 - 如果方法体只有一行代码,可以省略
{}和;同时return也可以省略。
JDK8新特性:方法引用
标志性符号:
::
分类:
- 静态方法的引用
- 实例方法的引用
- 特定类型方法的引用
- 构造器引用
注意:
方法引用只是一种简化代码的方式,在开发中不要刻意去简化。
随机数
点击查看代码
Random r = new Random();
int index = r.nextInt(4);//生成int类型的随机数,范围0,1,2,3