1. 集合架构
Collection 接口存储一组不唯一,无序的对象
List 接口存储一组不唯一,有序(索引顺序)的对象
Set 接口存储一组唯一,无序的对象
Map接口存储一组键值对象,提供key到value的映射
Key 唯一 无序
value 不唯一 无序
方法摘要 | |
---|---|
boolean | add(E e)向列表的尾部添加指定的元素(可选操作)。 |
void | [add](mk:@MSITStore:C:\Users\Administrator\Desktop\JDK_API_1_6_zh_CN.CHM::/java/util/List.html#add(int, E))(int index, E element) 在列表的指定位置插入指定元素(可选操作)。 |
boolean | addAll(Collection<? extends E> c) 添加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序(可选操作)。 |
boolean | [addAll](mk:@MSITStore:C:\Users\Administrator\Desktop\JDK_API_1_6_zh_CN.CHM::/java/util/List.html#addAll(int, java.util.Collection))(int index, Collection<? extends E> c) 将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。 |
void | clear() 从列表中移除所有元素(可选操作)。 |
boolean | contains(Object o) 如果列表包含指定的元素,则返回 true。 |
boolean | containsAll(Collection<?> c) 如果列表包含指定 collection 的所有元素,则返回 true。 |
E | get(int index) 返回列表中指定位置的元素。 |
boolean | isEmpty() 如果列表不包含元素,则返回 true。 |
Iterator | iterator() 返回按适当顺序在列表的元素上进行迭代的迭代器。 |
E | remove(int index) 移除列表中指定位置的元素(可选操作)。 |
boolean | remove(Object o) 从此列表中移除第一次出现的指定元素(如果存在)(可选操作)。 |
boolean | removeAll(Collection<?> c) 从列表中移除指定 collection 中包含的其所有元素(可选操作)。 |
boolean | retainAll(Collection<?> c) 仅在列表中保留指定 collection 中所包含的元素(可选操作)。 |
E | [set](mk:@MSITStore:C:\Users\Administrator\Desktop\JDK_API_1_6_zh_CN.CHM::/java/util/List.html#set(int, E))(int index, E element) 用指定元素替换列表中指定位置的元素(可选操作)。 |
int | size() 返回列表中的元素数。 |
2.Collection:
创建集合:Collection coll = new ArrayList<>();
coll.add();添加数据
.addAll();添加一个集合
.size();查看集合的元素数量
.isEmpty();清空集合内的元素
.contaise();查看是否包含
3.ArrayList:
有序(添加顺序) 不唯一
ArrayList list = new ArrayList<>();
list.add(11);添加元素
list.add(“你好”);
list.add(new Date().toLocaleString());
//将指定元素 添加到指定位置
list.add(1, “世界”);
//判断指定元素是否在集合内
list.contains(“世界”);
//获取指定位置的元素
Object o = list.get(2);
//删除指定的元素 删除成功返回true
boolean b = list.remove(“你好1”);
//返回删除的元素
Object remove = list.remove(0);
list.size();
//ArrayList 集合 下标 0开始 数量-1结束或获取最后一个元素
list.get(list.size() - 1);
//清空集合的内容
list.clear();
System.out.println("list1: "+list1);
//有对应的值 返回下标 没有对应的值 就返回-1
int index = list.indexOf(“你好1”);
//修改指定位置的值
list.set(0, 666);
//取两个集合的交集
list.retainAll(list2);
//Integer 类型的集合 在删除元素时 一定要手动进行包装
list.remove(Integer.valueOf(2));
4.LinkedList:
有序(添加顺序) 不唯一
创建集合对象、链表、操作头尾的方法
list.addFirst(“范冰冰”);将数据添加到第一个
list.add(0, “李冰冰”);
//添加到最后
list.addLast(“迪丽热巴”);
list.add(list.size()-1, “古力娜扎”);
list.getFirst();
list.getLast();
//返回删除的元素
String first = list.removeFirst();
String last = list.removeLast();
//设置指定位置的元素
list.set(0, “孙丽”);
equals:底层采用的是一 一对应进行比较
第二节ArrayList和LinkedList
5.理解 ArrayList的源码
ArrayList底层就是一个长度可以动态增长的Object数组;(StringBuilder底层就是一个长度可以动态增长的char数组)
JDK1.7中,使用无参数构造方法创建ArrayList对象时,默认底层数组长度是10。JDK1.8中,使用无参数构造方法创建ArrayList对象时,默认底层数组长度是0;第一次添加元素,容量不足就要进行扩容了。
容量不足时进行扩容,默认扩容50%。如果扩容50%还不足容纳新增元素,就扩容为能容纳新增元素的最小数量。(也就是1.5倍)(采用位运算 >>1 右移1位除以2 左移一位*2)
LinkedList增加了哪些方法
增加了对添加、删除、获取首尾元素的方法
addFirst()、addLast()、removeFirst()、removeLast()、getFirst()、getLast()、
6.理解LinkedList的底层源码
底层结构是一个双向链表。
有一个静态内部类Node,表示双向链表的节点。
LinkedList实现了Deque接口,所以除了可以作为线性表来使用外,还可以当做队列和栈来使用
7.ArrayList与LinkedList的区别
(1)底层存储的数据结构不一样
ArrayList:数组
LinkedList:链表
(2)在获取元素的时候
ArrayList:可以直接定位想要获取的元素
LinkedList:从头到尾进行遍历
(3)删除、添加的时候
ArrayList:牵一发而动全身,会有元素的移动
LinkedList:通过节点的增加或删除完成,不会影响其他的元素
(4)LinkedList:新增操作头尾的方法
8.使用 LinkedList 模拟 栈和队列的操作
栈: 后进先出
队列:先进先出
模拟栈的操作:
Deque deque = new LinkedList<>();
deque.push(10);
deque.push(20);
deque.push(30);
deque.pop();//出栈 弹栈
System.out.println(deque.peek());获取
模拟队列:
Queue queue = new LinkedList();
queue.add(66);
queue.add(88);
queue.add(99);
queue.poll();//删除队头/首
System.out.println(queue.peek());//获取队头元素
9.Set集合:
无序、唯一(数据元素不重复)
HashSet:无序、唯一
set接口相较于Collection接口,并没有新增任何方法
.clear()清空集合
.remove()删除
理解 HashSet的源码
HashSet的底层使用的是HashMap,所以底层结构也是哈希表
HashSet的元素到HashMap中做key,value统一是同一个Object()
LinkedHashSet:有序(按照添加的顺序)、唯一
.isEmpty()当集合内没有元素时返回true
TreeSet:有序(自然循序)、唯一
理解 TreeSet的源码
TreeSet的底层使用的是TreeMap,所以底层结构也是红黑树
TreeSet的元素e是作为TreeMap的key存在的,value统一为同一个 Object()
10.hash表的结构或:
顺序表+ 链表
1.计算要存入数据的hash码 hashCode()
2.根据hash码 来计算 在hash表内顺序表中的位置
3.添加
(1) 对应位置没有数据 直接添加
(2) 对应位置有数据 进行比较 equals() 当 要添加的数据 和已经存在的数据 不重复 "向后"添加
(3) 对应位置有数据 进行比较 equals() 当 要添加的数据 和已经存在的数据 重复 不添加
(4)要想使用HashSet LinkedHashSet 实现 唯一效果 必须重写hashCode()和 equals() 方法
11.Map集合:
方法摘要 | |
---|---|
void | clear() 从此映射中移除所有映射关系(可选操作)。 |
boolean | containsKey(Object key) 如果此映射包含指定键的映射关系,则返回 true。 |
boolean | containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true。 |
[Set] | entrySet() 返回此映射中包含的映射关系的 Set 视图。 |
boolean | equals(Object o) 比较指定的对象与此映射是否相等。 |
V | get(Object key) 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。 |
int | hashCode() 返回此映射的哈希码值。 |
boolean | isEmpty() 如果此映射未包含键-值映射关系,则返回 true。 |
[Set] | keySet() 返回此映射中包含的键的 Set 视图。 |
V | [put](mk:@MSITStore:C:\Users\Administrator\Desktop\JDK_API_1_6_zh_CN.CHM::/java/util/Map.html#put(K, V))(K key, V value) 将指定的值与此映射中的指定键关联(可选操作)。 |
void | putAll(Map<? extends K,? extends V> m) 从指定映射中将所有映射关系复制到此映射中(可选操作)。 |
V | remove(Object key) 如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。 |
int | size() 返回此映射中的键-值映射关系数。 |
[Collection] | values() 返回此映射中包含的值的 Collection 视图。 |
HashMap:
无序、唯一
底层默认容量为16
HashMap<Integer,String> map = new HashMap<>();
Integer:指的是键,也就是key String:指的是值,也就是value
1.存储的是 键值对
2.key是不能重复的, 当key重复了 后出现的value会覆盖前面的value
3.value是可以重复的
添加
map.put(1, “英国”);
map.put(2, “China”);
//通过key获取value
String in = map.get(“in”);
//返回删除的键值对
String en = map.remove(“en”);
//获取所有的key
Set keys = map.keySet();
//获取所有的value
Collection values = map.values();
含有多少元素不含重复的
int size = map.size();
判断值是否为空
boolean empty = map.isEmpty();
//替换指定key的value
map.replace(“in”, “印度”);
LinkedHashMap:有序(添加的顺序)、唯一
//Entry 中存储的就是 键值对
Set<Map.Entry<Integer, String>> entries = map.entrySet();
TreeMap:
有序(按key的自然顺序)、唯一
如果在key的位置添加自定义数据则必须使用内部比较器或外部比较器
每个节点的结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TcYBO9i1-1595140509331)(E:\有道云图片\qq433A8C57C88B51E6DF4A4B18D16012EA\c20ac39f46b840b4a6bd8144f24875aa\clipboard.png)]
键 值 左边的 正确的 根源 颜色
遍历:
方式一:
//存储的是map中所有的key
Set keys = map.keySet();
for(Integer key:keys){
System.out.println(key+" : "+map.get(key));
}
方式二:
Iterator iterator = keys.iterator();
while (iterator.hasNext()){
Integer key = iterator.next();
System.out.println(key+" : "+map.get(key));
}
方式三:
Set<Map.Entry<String,String>> entries = map.entrySet();拿到键值对
for(Map.Entry ele : entries){
System.out.println(ele);
System.out.println(ele.getKey()+"<=====>"+ele.getValue());
}
12.Iterator集合
Iterator专门为遍历集合而生,集合并没有提供专门的遍历的方法
Iterator实际上迭代器设计模式的实现
Iterator的常用方法
boolean hasNext(): 判断是否存在另一个可访问的元素
Object next(): 返回要访问的下一个元素
void remove(): 删除上次访问返回的对象。
哪些集合可以使用Iterator遍历
层次1:Collection、List、Set可以、Map不可以
层次2:提供iterator()方法的就可以将元素交给Iterator;
层次3:实现Iterable接口的集合类都可以使用迭代器遍历
for-each循环和Iterator的联系
for-each循环(遍历集合)时,底层使用的是Iterator
凡是可以使用for-each循环(遍历的集合),肯定也可以使用Iterator进行遍历
for-each循环和Iterator的区别
for-each还能遍历数组,Iterator只能遍历集合
使用for-each遍历集合时不能删除元素,会抛出异常ConcurrentModificationException使用Iterator遍历合时能删除元素
Iterator是一个接口,它的实现类在哪里?
在相应的集合实现类中 ,比如在ArrayList中存在一个内部了Itr implements Iterator
为什么Iterator不设计成一个类,而是一个接口
不同的集合类,底层结构不同,迭代的方式不同,所以提供一个接口,让相应的实现类来实现
ListIterator
ListIterator和Iterator的关系
public interface ListIterator<E> extends Iterator<E>
都可以遍历List
ListIterator和Iterator的区别
使用范围不同
Iterator可以应用于更多的集合,Set、List和这些集合的子类型。
ListIterator只能用于List及其子类型。
遍历顺序不同
Iterator只能顺序向后遍历; ListIterator还可以逆序向前遍历
Iterator可以在遍历的过程中remove();ListIterator可以在遍历的过程中remove()、add()、set()
ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
Collentions:
//添加元素
List list = new ArrayList();
Collections.addAll(list, 10, 50, 30, 90, 85, 100);
//排序
Collections.sort(list);//默认按照内部比较器
//查找元素(元素必须有序)
int index = Collections.binarySearch(list, 500);//不存在返回负数
//获取最大值和最小值
int max = Collections.max(list);
int min = Collections.min(list);
//填充集合
Collections.fill(list, null);
//复制集合
List list2 = new ArrayList();
Collections.addAll(list2, 10, 20, 30, 50);
dest.size >= src.size 目标列表的长度至少必须等于源列表。
Collections.copy(list, list2);
//同步集合
//StringBuffer 线程安全效率低 StringBuilder 线程不安全,效率高
//Vector 线程安全 效率低 ArrayList 线程不安全,效率高
//难道是要性能不要安全吗,肯定不是。
//在没有线程安全要求的情况下可以使用ArrayList
//如果遇到了线程安全的情况怎么办
//方法1:程序员手动的将不安全的变成安全的
//方法2:提供最新的线程安全并且性能高的集合类
//将list3转换成线程安全的集合类
list3 = Collections.synchronizedList(list3);
13.泛型:
T:type E:element K:key V:value
规定输入数据的类型
(1)声明在接口处,就是泛型接口
public interface Iterable
(2)泛型类:将泛型的声明放到类的声明处
public class LinkedList
(3)泛型方法:将泛型放到方法的返回值前
public staticvoid add( t)
(4)上限和下限
上限:<?extends E>最大只能是E
下限:<?superE>最小值能是E
任意类型:
位置类型:<?>
(5)存在编译阶段,运行时泛型会消失叫泛型擦除
14.旧的集合类:
Vector:线程安全 扩容到原来的2倍
ArrayList:线程不安全 扩容到原来的1.5倍
Hashtable:线程安全 键值不能为null
HashMap:线程不安全 键可以为null,值不可以为null
15.新一代并发集合类:
ConcurrentHashMap: 分段(segment)锁定+Lock锁
CopyOnWriteArrayList :CopyOnWrite+Lock锁
CopyOnWrite原理:添加时,写时复制再加锁,读不需要加锁
· CopyOnWriteArraySet:CopyOnWrite+Lock锁,写的时候加锁
16.集合和数组的比较
数组不是面向对象的,存在明显的缺陷,集合完全弥补了数组的一些缺点,比数组更灵活更实用,可大大提高软件的开发效率而且不同的集合框架类可适用于不同场合。具体如下:
1 : 数组容量固定且无法动态改变,集合类容量动态改变。
2:数组能存放基本数据类型和引用数据类型的数据,而集合类中只能放引用数据类型的数据。
3:数组无法判断其中实际存有多少元素,length只告诉了array容量;集合可以判断实际存有多少元素,而对总的容量不关心
4:集合有多种数据结构(顺序表、链表、哈希表、树等)、多种特征(是否有序,是否唯一)、不同适用场合(查询快,便于删除、有序),不像数组仅采用顺序表方式
5:集合以类的形式存在,具有封装、继承、多态等类的特性,通过简单的方法和属性调用即可实现各种复杂操作,大大提高软件的开发效率。
存储结构 | 顺序 | 唯一 | 查询 | 添加/删除 | |
---|---|---|---|---|---|
ArrayList | 顺序表 | 有序(添加) | 不唯一 | 索引查询效率最高 | 效率低 |
LinkedList | 双向链表 | 有序(添加) | 不唯一 | 效率低 | 效率高 |
HashSet | 哈希表 | 无序 | 唯一 | 效率最高 | 效率最高 |
HashMap | 哈希表 | Key无序 | key唯一 | 效率最高 | 效率最高 |
LinkedHashSet | 哈希表+链表 | 有序(添加) | 唯一 | 效率最高 | 效率最高 |
LinkedHashMap | 哈希表+链表 | Key有序(添加) | key唯一 | 效率最高 | 效率最高 |
TreeSet | 红黑树 | 有序(自然) | 唯一 | 效率中等 | 效率中等 |
TreeMap | 红黑树 | 有序(自然) | key唯一 | 效率中等 | 效率中等 |
Collection | Map | |||
---|---|---|---|---|
无序 不唯一 | Collection | Map.values() | ||
有序 不唯一 | ArrayList | LinkedList | ||
无序 唯一 | HashSet | HashMap keySet | ||
有序 唯一 | LinkedHashSet | TreeSet | LinkedHashMap keySet | TreeMap keySet |
17.Lambda表达式
语法:
(parameters) -> expression或 (parameters) ->{ statements; }
参数:要重写的方法的形参列表
-> :lambda运算符
表达式/语句体:要重写的方法的方法体
-
无参数无返回值
-
一个参数无返回值
-
多个参数无返回值
-
有参数有返回值
总结:
->左面:
参数类型可以省略不写!->类型推断
如果只有一个参数,()可以省略不写
->右侧:
{}将方法体的具体内容包裹起来
只有一个方法体执行语句的话,{}可以省略不写
如果一句执行语句是return语句,return可以省略不写
18.函数接口:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zyo72CDT-1595140509344)(E:\有道云图片\qq433A8C57C88B51E6DF4A4B18D16012EA\aa25239d727c46138de4c926194c2c68\7noh~nd}tp%5zs@bn_z0bog.png)]
函数式接口:
@FunctionalInterface 编译检查
只能有一个抽象方法 可以存在多种方法
内置函数式接口:
Consumer:消费型接口(void accept(T t))。有参数,无返回值
Supplier:供给型接口(T get())。只有返回值,没有入参
Function<T, R>:函数型接口(R apply(T t))。一个输入参数,一个输出参数,两种类型不可不同、可以一致
Predicate:断言型接口(boolean test(T t))。输入一个参数,输出一个boolean类型得返回值
19.方法的引用:符号::
-
对象引用::实例方法名
-
类名::静态方法名
-
类名::实例方法名
-
类名::new (也称为构造方法引用)
-
类型[]::new (也称为数组引用)
20.流式编程Stream
Stream有如下三个操作步骤:
一、创建Stream:从一个数据源,如集合、数组中获取流。
二、中间操作:一个操作的中间链,对数据源的数据进行操作。
三、终止操作:一个终止操作,执行中间操作链,并产生结果。
创建Stream流
Stream stream = list.stream().sorted();
进行中间操作
stream = stream.sorted()//排序
.distinct()//去重
.map((x)->2+x)//给每一个值进行映射 在原来值的基础上+2
.filter((x)-> x>2?true:false)//过滤数据
.skip(1)//跳过 2个值
.limit(4);//只能有4个元素
//终止操作
stream.forEach(System.out::println);//遍历
Optional first = stream.findFirst();
System.out.println(first);