1.集合体系结构
List系列集合:添加的元素是有序、可重复、有索引
set系列集合:添加的元素是无需、不重复、无索引
2.Collection
Collection是单列集合的祖宗接口,它的功能是全部单列集合都可以继承使用的
2
2.1Collection的遍历方式
2.1.1迭代器遍历
迭代器在java中的类是iterator,迭代器是集合专用的遍历方式
获取迭代器
常用方法
代码示例
public class IteratorDemo1 {
public static void main(String[] args) {
//创建集合对象
Collection<String> c = new ArrayList<>();
//添加元素
c.add("hello");
c.add("world");
c.add("java");
c.add("javaee");
//Iterator<E> iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
Iterator<String> it = c.iterator();
//用while循环改进元素的判断和获取
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
}
}
删除方法
public class IteratorDemo2 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("b");
list.add("c");
list.add("d");
Iterator<String> it = list.iterator();
while(it.hasNext()){
String s = it.next();
if("b".equals(s)){
//指向谁,那么此时就删除谁.
it.remove();
}
}
System.out.println(list);
}
}
2.1.2增强for循环
它是JDK5之后出现的,其内部原理是一个Iterator迭代器
实现Iterable接口的类才可以使用迭代器和增强for
简化数组和Collection集合的遍历
格式:
for(集合/数组中元素的数据类型 变量名 : 集合/数组名) {
// 已经将当前遍历到的元素封装到变量中了,直接使用变量即可
}
代码示例
public class MyCollectonDemo1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
//1,数据类型一定是集合或者数组中元素的类型
//2,str仅仅是一个变量名而已,在循环的过程中,依次表示集合或者数组中的每一个元素
//3,list就是要遍历的集合或者数组
for(String str : list){
System.out.println(str);
}
}
}
2.1.3 Lambda表达式
利用forEach方法,再结合lambda表达式的方式进行遍历
代码示例:
public class A07_CollectionDemo7 {
public static void main(String[] args) {
/*
lambda表达式遍历:
default void forEach(Consumer<? super T> action):
*/
//1.创建集合并添加元素
Collection<String> coll = new ArrayList<>();
coll.add("zhangsan");
coll.add("lisi");
coll.add("wangwu");
//2.利用匿名内部类的形式
//底层原理:
//其实也会自己遍历集合,依次得到每一个元素
//把得到的每一个元素,传递给下面的accept方法
//s依次表示集合中的每一个数据
/* coll.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});*/
//lambda表达式
coll.forEach(s -> System.out.println(s));
}
}
3 List集合
特点:
有序:存和取的元素顺序一致
有索引:可以同股票索引操作元素
可重复:存储的元素可以重复
3.1方法
Collection的方法List都继承了
List集合因为有索引,所以多了很多索引的操作方法
4.数据结构
概述:数据结构是计算机底层存储、组织数据的方式。
是指数据相互之间是以什么方式排列在一起的。
数据结构是为了更加方便地管理和使用数据,需要结合具体的业务场景来进行选择。
一般情况下,精心选择的数据结构可以带来更高的运行或者存储效率
4.1栈
特点:后进先出,先进后出
数据进入栈模型的过程称为:压/进栈
数据离开栈模型的过程被称为:弹/出栈
4.2队列
特点:先进先出,后进后出
4.3数组
特点:查询快,增删慢
4.4ArrayList集合
特点:底层是数组结构实现,查询快、增删慢
4.6LinkedList集合
特点:底层是链表结构实现,查询慢、增删快
示例代码:
public class MyLinkedListDemo4 {
public static void main(String[] args) {
LinkedList<String> list = new LinkedList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
// public void addFirst(E e) 在该列表开头插入指定的元素
//method1(list);
// public void addLast(E e) 将指定的元素追加到此列表的末尾
//method2(list);
// public E getFirst() 返回此列表中的第一个元素
// public E getLast() 返回此列表中的最后一个元素
//method3(list);
// public E removeFirst() 从此列表中删除并返回第一个元素
// public E removeLast() 从此列表中删除并返回最后一个元素
//method4(list);
}
private static void method4(LinkedList<String> list) {
String first = list.removeFirst();
System.out.println(first);
String last = list.removeLast();
System.out.println(last);
System.out.println(list);
}
private static void method3(LinkedList<String> list) {
String first = list.getFirst();
String last = list.getLast();
System.out.println(first);
System.out.println(last);
}
private static void method2(LinkedList<String> list) {
list.addLast("www");
System.out.println(list);
}
private static void method1(LinkedList<String> list) {
list.addFirst("qqq");
System.out.println(list);
}
}
5.泛型
泛型是JDK5中引入的特性,它提供了编译时类型安全检测机制
好处:
1. 把运行时期的问题提前到了编译期间
2. 避免了强制类型转换
定义格式:
<类型>: 指定一种类型的格式.尖括号里面可以任意书写,一般只写一个字母.例如: <E> <T>
<类型1,类型2…>: 指定多种类型的格式,多种类型之间用逗号隔开.例如: <E,T> <K,V>
6.数据结构(二叉查找树)
6.1二叉数
特点:
二叉树中,任意一个节点的度要小于等于2
节点: 在树结构中,每一个元素称之为节点
度: 每一个节点的子节点数量称之为度
6.2 二叉查找树
特点:
二叉查找树,又称二叉排序树或者二叉搜索树
每一个节点上最多有两个子节点
左子树上所有节点的值都小于根节点的值
右子树上所有节点的值都大于根节点的值
二叉树与二叉查找树的对比图
添加节点规则
小的存左边,大的存右边,一样的不存
6.3 平衡二叉树
特点:
二叉树左右两个子树的高度差不超过1
任意节点的左右两个子树都是一颗平衡二叉树
旋转触发时机:
当添加一个节点之后,该树不再是一颗平衡二叉树
左旋:就是将根节点的右侧往左拉,原先的右子节点变成新的父节点,并把多余的左子节点出让,给已经降级的根节点当右子节点
右旋:就是将根节点的左侧往右拉,左子节点变成了新的父节点,并把多余的右子节点出让,给已经降级根节点当左子节点
旋转的四种情况:
1.左左:当根节点左子树的左子树有节点插入,导致二叉树不平衡。整体进行右旋即可
2.左右:当根节点左子树的右子树有节点插入,导致二叉树不平衡。先在左子树对应的节点位置进行左旋,在对整体进行右旋
3.右右:当根节点右子树的右子树有节点插入,导致二叉树不平衡。整体进行左旋即可
4.右左:当根节点右子树的左子树有节点插入,导致二叉树不平衡。先在右子树对应的节点位置进行右旋,在对整体进行左旋
6.4红黑树
特点:
平衡二叉B树,每一个节点可以是红或者黑。红黑树不是高度平衡的,它的平衡是通过"自己的红黑规则"进行实现的
规则:
1. 每一个节点或是红色的,或者是黑色的
2. 根节点必须是黑色
3. 如果一个节点没有子节点或者父节点,则该节点相应的指针属性值为Nil,这些Nil视为叶节点,每个叶节点(Nil)是黑色的
4. 如果某一个节点是红色,那么它的子节点必须是黑色(不能出现两个红色节点相连 的情况)
5. 对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点
6. set集合
概述及特点:
不可以存储重复元素
没有索引,不能使用普通for循环遍历
6.1set集合的使用
存储字符串并遍历
public class MySet1 {
public static void main(String[] args) {
//创建集合对象
Set<String> set = new TreeSet<>();
//添加元素
set.add("ccc");
set.add("aaa");
set.add("aaa");
set.add("bbb");
// for (int i = 0; i < set.size(); i++) {
// //Set集合是没有索引的,所以不能使用通过索引获取元素的方法
// }
//遍历集合
Iterator<String> it = set.iterator();
while (it.hasNext()){
String s = it.next();
System.out.println(s);
}
System.out.println("-----------------------------------");
for (String s : set) {
System.out.println(s);
}
}
}
7.TreeSet集合
概述:
不可以存储重复元素。
没有索引。
可以将元素按照规则进行排序。
TreeSet():根据其元素的自然排序进行排序
TreeSet(Comparator comparator) :根据指定的比较器进行排序
代码实现:
public class TreeSetDemo01 {
public static void main(String[] args) {
//创建集合对象
TreeSet<Integer> ts = new TreeSet<Integer>();
//添加元素
ts.add(10);
ts.add(40);
ts.add(30);
ts.add(50);
ts.add(20);
ts.add(30);
//遍历集合
for(Integer i : ts) {
System.out.println(i);
}
}
}
8.双列集合
特点:
1.双列集合一次需要存一对数据,分别为键和值
2.键不能重复,值可以重复
3.键和值是一一对应的,每一个键只能找到自己对应的值
4.键+值这个整体,我们称之为“键对值”或者“键值对对象”,在java中叫做“Entry对象”
8.1Map常见的API
Map是双列集合的顶层接口,它的功能是全部双列集合都可以继承使用的
put方法的细节:
添加/覆盖
在添加数据的时候,如果键不存在,那么直接把键值对对象添加到Map集合当中,方法返回null
在添加数据的时候,如果键是存在的,那么会把原有的键值对对象覆盖,会把覆盖的键值进行返回。
代码实现:
package HashMap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
public class demo1 {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("尹志平", "小龙女");
map.put("郭靖", "黄蓉");
map.put("欧阳克", "欧阳修");
//通过键找值
Set<String> keys = map.keySet();
// for (String key : keys) {
System.out.println(key);
// // 利用map集合中的键来获取对应的值 get方法
// String s = map.get(key);
// System.out.println(key+"="+s);
// }
迭代器
// Iterator<String> iterator = keys.iterator();
// while (iterator.hasNext()){
// String next = iterator.next();
// // 利用map集合中的键来获取对应的值 get方法
// String s = map.get(next);
// System.out.println(next+"="+s);
System.out.println(next);
// }
//lambda
keys.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
String next=map.get(s);
System.out.println(s+"="+next);
}
});
}
}
8.1.1Map的遍历方式1
获取所有键的集合。用keySet()方法实现
遍历键的集合,获取到每一个键。用增强for实现
根据键去找值。用get(Object key)方法实现
public class MapDemo01 {
public static void main(String[] args) {
//创建集合对象
Map<String, String> map = new HashMap<String, String>();
//添加元素
map.put("张无忌", "赵敏");
map.put("郭靖", "黄蓉");
map.put("杨过", "小龙女");
//获取所有键的集合。用keySet()方法实现
Set<String> keySet = map.keySet();
//遍历键的集合,获取到每一个键。用增强for实现
for (String key : keySet) {
//根据键去找值。用get(Object key)方法实现
String value = map.get(key);
System.out.println(key + "," + value);
}
}
}
8.1.1Map的遍历方式2
获取所有键值对对象的集合
Set<Map.Entry<K,V>> entrySet():获取所有键值对对象的集合
遍历键值对对象的集合,得到每一个键值对对象
用增强for实现,得到每一个Map.Entry
根据键值对对象获取键和值
用getKey()得到键
用getValue()得到值
public class MapDemo02 {
public static void main(String[] args) {
//创建集合对象
Map<String, String> map = new HashMap<String, String>();
//添加元素
map.put("张无忌", "赵敏");
map.put("郭靖", "黄蓉");
map.put("杨过", "小龙女");
//获取所有键值对对象的集合
Set<Map.Entry<String, String>> entrySet = map.entrySet();
//遍历键值对对象的集合,得到每一个键值对对象
for (Map.Entry<String, String> me : entrySet) {
//根据键值对对象获取键和值
String key = me.getKey();
String value = me.getValue();
System.out.println(key + "," + value);
}
}
}
8.2HashMap
特点:HashMap是Map里面的一个实现类。
2.没有额外学习的特有方法,直接使用Map里面的方法就可以了
3.特点都是由键决定的:无序、不重复、无索引
4.HashMap和HashSet底层原理是一模一样的,都是哈希表结构
8.3LinkHashMap
1.由键决定:有序、不重复、无索引
2.有序指的是保证存储和取出的元素顺序一致
3.原理:底层数据结构依然是哈希表,只是每个键值的元素又额外的多了一个双链表的机制记录存储的顺序
8.4TreeMap
1.TreeMap跟TreeSet底层原理一样,都是红黑树结构。
2.由键决定特性:不重复、无索引、可排序
3.可排序:对键进行排序
4.默认按照键的从小到大进行排序,也可以自己规定键的排序规则
排序规则:
1.实现comparable接口,指定比较规则
2.创建集合时传递comparable比较器对象,指定比较规则
8.5可变参数
可变参数本质上就是一个数组
作用:在形参中接收多个数据
格式:数据类型...参数名称
举例:int...a
注意事项:
形参列表中可变参数只能有一个
可变参数必须放在形参列表的最后面
8.6Collections
java.util.Collections:是集合工具类
作用:Collections不是集合,而是集合的工具类
常用的api:
9.不可变集合
特点:定义完成后不可以修改,或者添加、删除
书写格式:
在List、set、map接口中,都存在静态的of方法,可以获取一个不可变的集合
不可变list集合:
public class ImmutableDemo1 {
public static void main(String[] args) {
/*
创建不可变的List集合
"张三", "李四", "王五", "赵六"
*/
//一旦创建完毕之后,是无法进行修改的,在下面的代码中,只能进行查询操作
List<String> list = List.of("张三", "李四", "王五", "赵六");
System.out.println(list.get(0));
System.out.println(list.get(1));
System.out.println(list.get(2));
System.out.println(list.get(3));
System.out.println("---------------------------");
for (String s : list) {
System.out.println(s);
}
System.out.println("---------------------------");
Iterator<String> it = list.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
System.out.println("---------------------------");
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
System.out.println(s);
}
System.out.println("---------------------------");
//list.remove("李四");
//list.add("aaa");
list.set(0,"aaa");
}
set集合
public class ImmutableDemo2 {
public static void main(String[] args) {
Set<String> set = Set.of("张三", "张三", "李四", "王五", "赵六");
for (String s : set) {
System.out.println(s);
}
System.out.println("-----------------------");
Iterator<String> it = set.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
System.out.println("-----------------------");
//set.remove("王五");
}
}
细节:当我们要获取一个不可变的Set集合时,里面的参数一定要保证唯一性
map(键值对小于等于10)
public class ImmutableDemo3 {
public static void main(String[] args) {
/*
创建Map的不可变集合
细节1:
键是不能重复的
细节2:
Map里面的of方法,参数是有上限的,最多只能传递20个参数,10个键值对
细节3:
如果我们要传递多个键值对对象,数量大于10个,在Map接口中还有一个方法
*/
//一旦创建完毕之后,是无法进行修改的,在下面的代码中,只能进行查询操作
Map<String, String> map = Map.of("张三", "南京", "张三", "北京", "王五", "上海",
"赵六", "广州", "孙七", "深圳", "周八", "杭州",
"吴九", "宁波", "郑十", "苏州", "刘一", "无锡",
"陈二", "嘉兴");
Set<String> keys = map.keySet();
for (String key : keys) {
String value = map.get(key);
System.out.println(key + "=" + value);
}
System.out.println("--------------------------");
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "=" + value);
}
System.out.println("--------------------------");
}
}
大于10
public class ImmutableDemo4 {
public static void main(String[] args) {
/*
创建Map的不可变集合,键值对的数量超过10个
*/
//1.创建一个普通的Map集合
HashMap<String, String> hm = new HashMap<>();
hm.put("张三", "南京");
hm.put("李四", "北京");
hm.put("王五", "上海");
hm.put("赵六", "北京");
hm.put("孙七", "深圳");
hm.put("周八", "杭州");
hm.put("吴九", "宁波");
hm.put("郑十", "苏州");
hm.put("刘一", "无锡");
hm.put("陈二", "嘉兴");
hm.put("aaa", "111");
//2.利用上面的数据来获取一个不可变的集合
/*
//获取到所有的键值对对象(Entry对象)
Set<Map.Entry<String, String>> entries = hm.entrySet();
//把entries变成一个数组
Map.Entry[] arr1 = new Map.Entry[0];
//toArray方法在底层会比较集合的长度跟数组的长度两者的大小
//如果集合的长度 > 数组的长度 :数据在数组中放不下,此时会根据实际数据的个数,重新创建数组
//如果集合的长度 <= 数组的长度:数据在数组中放的下,此时不会创建新的数组,而是直接用
Map.Entry[] arr2 = entries.toArray(arr1);
//不可变的map集合
Map map = Map.ofEntries(arr2);
map.put("bbb","222");*/
//Map<Object, Object> map = Map.ofEntries(hm.entrySet().toArray(new Map.Entry[0]));
Map<String, String> map = Map.copyOf(hm);
map.put("bbb","222");
}
}
10.Stream流
作用:结合了Lambda表达式,简化集合、数组的操作
使用步骤
1.先得到一条stream流,并把数据放上去
package Stream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.stream.Stream;
public class demo2 {
public static void main(String[] args) {
//单列集合
ArrayList<String> list=new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
list.stream().forEach(s-> System.out.println(s));
System.out.println("============================");
//双列集合
HashMap<String,String> list2=new HashMap<>();
list2.put("北京","圆明园");
list2.put("上海","双子塔");
list2.put("长沙","橘子洲头");
list2.put("杭州","体育馆");
list2.entrySet().stream().forEach(s-> System.out.println(s));
//数组
int[] it={1,2,3,4,5};
String [] str={"张三","wa","www"};
Arrays.stream(it).forEach(s-> System.out.println(s));
Arrays.stream(str).forEach(s-> System.out.println(s));
//零散数据
Stream.of(1,2,3,4,5,6,7,8).forEach(s-> System.out.println(s));
}
}
10.1中间方法
注:中间方法,返回新的stream流,原来的stream只能使用一次,建议使用链式编程。修改stream流中的数据,不会影响原来集合或者数组中的数据
10.2终结方法
11.方法引用
把已经有的方法拿过来用,当作函数式接口中抽象方法的方法体
1.引用处需要时函数式接口
2.被引用的方法需要依据存在
3.被引用方法的形参的返回值需要跟抽象方法的形参的返回值保持一致
4.被引用方法的功能需要满足当前的要求
注:“::“是方法引用符
package Fuction;
import java.util.Arrays;
import java.util.Comparator;
public class functionDemo1 {
public static void main(String[] args) {
Integer [] arr={4,5,3,2,6,8,7};
// Arrays.sort(arr, new Comparator<Integer>() {
// @Override
// public int compare(Integer o1, Integer o2) {
// return o2-o1;
// }
// });
// Arrays.sort(arr,(o1, o2) -> o2-01);
Arrays.sort(arr,functionDemo1::show);
System.out.println(Arrays.toString(arr));
}
public static int show(int num1,int num2){
return num2-num1;
}
}
11.1分类
引用静态方法、引用成员方法、引用构造方法
引用其他类的成员方法、引用本类的成员方法、引用父类的成员方法
11.1.1静态方法
格式:类名::静态方法
例:Integer::parseInt
代码示例:
package Fuction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.function.Function;
public class functionDemo2 {
public static void main(String[] args) {
ArrayList<String>list=new ArrayList<>();
Collections.addAll(list,"1","2","3","4","5");
// list.stream().map(new Function<String, Integer>() {
//
// @Override
// public Integer apply(String s) {
// int i = Integer.parseInt(s);
// return i;
// }
// }).forEach(s-> System.out.println(s));
list.stream().map(Integer::parseInt).forEach(s-> System.out.println(s));
}
}
11.1.2成员方法
格式:对象::成员方法
其他类:其它类对象:方法名
本类:this:方法名
父类:super:方法名
代码示例:
package Fuction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.function.Function;
import java.util.function.Predicate;
public class functionDemo2 {
public static void main(String[] args) {
ArrayList<String>list=new ArrayList<>();
Collections.addAll(list,"张无忌","张三","周若","张雪峰","张张张张张");
// list.stream().filter(s->s.startsWith("张")).filter(s->s.length()>=3).forEach(s-> System.out.println(s));
//list.stream().filter(new Predicate<String>() {
// @Override
// public boolean test(String s) {
// boolean i = s.startsWith("张") && s.length() >= 3;
// return i;
// }
//}).forEach(s-> System.out.println(s));
// list.stream().filter(new Stringjude()::test).forEach(s-> System.out.println(s));//调用其它类
list.stream().filter(new functionDemo2()::test).forEach(s-> System.out.println(s));//static不能使用this方法
}
public boolean test(String s) {
boolean i = s.startsWith("张") && s.length() >= 3;
return i;
}
}
11.1.2构造方法
格式:类名::new
例:student::new
例:
package Fuction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
public class FunctionDemo3 {
public static void main(String[] args) {
ArrayList<String >list =new ArrayList<>();
Collections.addAll(list,"张无忌,18","张三,17","周若,19","张雪峰,31","张张张张张,100");
List<Student>newList=list.stream().map(new Function<String, Student>() {
@Override
public Student apply(String s) {
String[] split = s.split(",");
String name=split[0];
int age=Integer.parseInt(split[1]);
return new Student(name,age);//返回一个对象
}
}).collect(Collectors.toList());
System.out.println(newList);
List<Student>newList2=list.stream().map(Student::new).collect(Collectors.toList());
System.out.println(newList2);
}
}
11.1.3类名调成员方法
格式:类名::成员方法
例:String::substring
例:集合小写字符变大写
package Fuction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Locale;
import java.util.function.Function;
public class functionDemo4 {
public static void main(String[] args) {
ArrayList<String> list=new ArrayList<>();
Collections.addAll(list,"aa","bb","cc","dd","ee");
// list.stream().map(new Function<String, String>() {
// @Override
// public String apply(String s) {
// String s1 = s.toUpperCase(Locale.ROOT);
// return s1;
// }
// }).forEach(s -> System.out.println(s));
list.stream().map(String::toUpperCase).forEach(s-> System.out.println(s));
}
}
11.1.4数组
格式:数据类型[]::new
例:int[]::new
例:集合存储整数,收集到数组当中
package Fuction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.function.IntFunction;
public class functionDemo5 {
public static void main(String[] args) {
ArrayList<Integer> list=new ArrayList<>();
Collections.addAll(list,1,2,3,4,5);
// Integer[] integers = list.stream().toArray(new IntFunction<Integer[]>() {
// @Override
// public Integer[] apply(int value) {
// return new Integer[value];
// }
// });
// System.out.println(Arrays.toString(integers));
Integer[] integers = list.stream().toArray(Integer[]::new);
System.out.println(Arrays.toString(integers));
}
}