集合的知识
集合
collection集合的常用方法
collection的特点
Collection代表单列集合,每个元素(数据)只包含一个值。
Map代表双列集合,每个元素包含两个值(键值对)。
Collection集合特点
由于collection是一个泛型,所以我们在定义的时候要用确定的类型来定义这个
- List系列集合:添加的元素是有序、可重复、有索引。
- ArrayList、LinekdList :有序、可重复、有索引。
- Set系列集合:添加的元素是无序、不重复、无索引。
- HashSet: 无序、不重复、无索引;
- LinkedHashSet: 有序、不重复、无索引。
- TreeSet:按照大小默认升序排序、不重复、无索引。
Collection集合有哪两大常用的集合体系,各自有啥特点?
List系列集合:添加的元素是有序、可重复、有索引。
Set系列集合:添加的元素是无序、不重复、无索引。
根据日常使用的需求,我们来挑选不同的集合
举例
public class CommonFunction {
public static void main(String[] args) {
//简单确认一下collection集合 的特点
ArrayList<String> arr = new ArrayList<>();
arr.add("qiu");
arr.add("ke");
arr.add("hao");
System.out.println(arr); //[qiu, ke, hao]有序、可重复、有索引。
HashSet<String> hah = new HashSet<>();
hah.add("qiu");
hah.add("ke");
hah.add("hao");
hah.add("hao");
System.out.println(hah); //[hao, ke, qiu]无序、不重复、无索引;
}
}
colllection的常用方法
这些方法是所有集合都能够进行使用的方法
方法名 | 说明 |
---|---|
public boolean add(E e) | 把给定的对象添加到当前集合中 |
public void clear() | 清空集合中所有的元素 |
public boolean remove(E e) | 把给定的对象在当前集合中删除 |
public boolean contains(Object obj) | 判断当前集合中是否包含给定的对象 |
public boolean isEmpty() | 判断当前集合是否为空 |
public int size() | 返回集合中元素的个数。 |
public Object[] toArray() | 把集合中的元素,存储到数组中 |
package colletion.CommonFunction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
public class collectionFunction {
public static void main(String[] args) {
Collection<String> c = new ArrayList<>();
c.add("qiu");
c.add("ke");
c.add("hao");
c.add("qiu");
System.out.println(c);
System.out.println(c.isEmpty());
System.out.println(c.size());
System.out.println("------------------------");
c.remove("qiu");
c.remove("k");
System.out.println(c);
System.out.println(c.size());
System.out.println(c.contains("qiu"));
System.out.println(c.contains("h"));
System.out.println("------------------------");
//在某些情况下,这个里面的数据类型并不一定都是字符串类型
Object[] arr = c.toArray();
System.out.println(Arrays.toString(arr));
//如果我们就是想让其转化为字符数组呢
String[] str = c.toArray(new String[c.size()]);
System.out.println(Arrays.toString(str));
System.out.println("------------------------");
c.clear();
System.out.println(c.isEmpty());
System.out.println(c.size());
}
}
collection 的遍历方法
迭代器
集合来调用这个迭代器的方法
然后我们再用这个Iterator类来获取这个返回对象
it.next()获取下一个值,并后移
it.hasnext()判断其后面有没有值
如果我们遍历的比较多的话,我们很有可能会造成这个迭代器越界,一定要注意
迭代器遍历的时候我们一定要注意这个迭代遍历不能在一段循环代码中,执行几次,否则的话,容易出错
Iterator<String> iter = c.iterator();
while (iter.hasNext()){
String s = iter.next();
System.out.println(s);
}
增强型for循环
可以用来遍历这个集合和数组
for(元素的数据类型 变量名 : 数组或者集合){
}
//增强for
for(String s : c){
System.out.println(s);
}
IDEA快捷for循环遍历,如果我们想用这个索引遍历就是 数组/集合名字.fori
如果是增强for循环就是数组.集合名字.for
lambda表达式
源码
foreach方法
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
其实foreach本质还是调用这个增强for循环
//lambda表达式
c.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
c.forEach(s->System.out.println(s));
//方法引用
c.forEach(System.out::println); //快速遍历方式,IDEA里的是c.foreach(sout);快速构建
案例
遍历电影,考验我们对于对象的遍历的理解,我们还可以通过重写这个toString方法,来进行快速遍历
movies.forEach(System.out::println); //我们可以通过重写内部类的toString方法来实现这个
package colletion.CommonFunction.movies;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class moviesOutput {
public static void main(String[] args) {
Collection<movie> movies = new ArrayList<>();
movies.add(new movie("《肖生克的救赎》", 9.7 , "罗宾斯"));
movies.add(new movie("《霸王别姬》", 9.6 , "张国荣、张丰毅"));
movies.add(new movie("《阿甘正传》", 9.5 , "汤姆.汉克斯"));
for (movie mov : movies) {
System.out.println("电影名: "+mov.getName());
System.out.println("得分: "+mov.getScore() );
System.out.println("演员: "+mov.getActor());
System.out.println("--------------------");
}
Iterator<movie> iterator = movies.iterator();
while (iterator.hasNext()){
System.out.println("电影名: "+iterator.next().getName());
System.out.println("得分: "+iterator.next().getScore() );
System.out.println("演员: "+iterator.next().getActor());
System.out.println("--------------------");
}
movies.forEach(System.out::println); //我们可以通过重写内部类的toString方法来实现这个
}
}
list
List系列集合特点: 有序,可重复,有索引
ArrayList:有序,可重复,有索引。
LinkedList:有序,可重复,有索引。
List和Collection都是接口,我们并不能够直接创建对象,我们要通过接口的方式来创建对象
常用方法
方法名称 | 说明 |
---|---|
void add(int index,E element) | 在此集合中的指定位置插入指定的元素 |
E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
E get(int index) | 返回指定索引处的元素 |
常用遍历方法
因为我们可以通过这个for循环索引遍历的方式
这个是因为这个list是有索引的,和这个collection不一样
list系列集合的底层原理
Arraylist
Arraylist集合的底层原理
其是基于 数组来实现的
特点是查询速度快,注意是根据索引查询速度快
- 查询数据通过地址值和索引定位,查询任意数据耗时相同
- 删除效率低,需要把后面很多的数据进行前移
- 添加效率第,需要把后面的数据后移,在添加元素,或者也有可能进行数组的扩容
构建原理
- 利用无参构造器创建的集合,会在底层创建一个默认长度为0的数组
- 添加第一个元素时,底层会创建一个新的长度为10的数组
- 存满时,会扩容1.5倍
- 如果一次添加多个元素,1.5倍还放不下,则新创建数组的长度以实际为准
适合根据索引查询数据,比如根据随机索引取数据,或者数据量不是很大的时候
不适合,数据量大的同时,又要频繁的进行增删操作
LinkList
基于双链表实现的。
链表中的结点是独立的对象,在内存中是不连续的,每个结点包含数据值和下一个结点的地址。
链表的特点1:查询慢,无论查询哪个数据都要从头开始找。
链表的特点2:链表增删相对快
单向链表
双向链表, 特点:查询慢,增删相对较快,但对首尾元素进行增删改查的速度是极快的。可以根据索引位置,选择从前,从后遍历
常用方法
队列
Linkedlist的应用场景之一,我们可以用来设计队列----先进先出
队列是一种常见的数据结构系统,是一种经常用来操作首尾数据的一种系统,比如说排队系统
LinkedList<String> queue = new LinkedList<>();
queue.addLast("11");
queue.addLast("22");
queue.add("55"); //add本身也是在最后面添加元素
queue.addLast("33");
queue.add("44");
System.out.println(queue);
LinkedList的引用场景之一,可以用来设计栈
栈的特点是:后进先出,先进后出
栈
数据进入栈模型的过程称为:压/进栈(push)
数据离开栈模型的过程称为:弹/出栈(pop)
LinkedList<String> stack = new LinkedList<>();
stack.addFirst("11");
stack.addFirst("22");
stack.addFirst("33");
System.out.println(stack);
System.out.println(stack.removeFirst());
System.out.println(stack.removeFirst());
System.out.println(stack.removeFirst());
从JDK6以后,java就在linkedlist里面添加了push和pop的API,其实就是换了个马甲
public void push(E e) {
addFirst(e);
}
public E pop() {
return removeFirst();
}
set
无序:添加数据的顺序和获取出的数据顺序不一致; 不重复; 无索引;
- HashSet : 无序、不重复、无索引。
- LinkedHashSet:有序、不重复、无索引。
- TreeSet:排序、不重复、无索引。会对你上传的数据,会自动进行排序,升序排序
注意:
Set要用到的常用方法,基本上就是Collection提供的!!
自己几乎没有额外新增一些常用功能!
其实不重复的
hashset
无序、不重复、无索引。
Set<Integer> set = new HashSet<>();
set.add(90);
set.add(80);
set.add(70);
set.add(70);
System.out.println(set);
//[80, 70, 90]
底层原理
注意:在正式了解HashSet集合的底层原理前,我们需要先搞清楚一个前置知识:哈希值!
哈希值
就是一个int类型的数值,Java中每个对象都有一个哈希值。
Java中的所有对象,都可以调用Obejct类提供的hashCode方法,返回该对象自己的哈希值
对象哈希值的特点
同一个对象多次调用hashCode()方法返回的哈希值是相同的。
不同的对象,它们的哈希值一般不相同,但也有可能会相同(哈希碰撞)。
比如说abc和acD
基于哈希表实现。
哈希表是一种增删改查数据,性能都较好的数据结构
- 创建一个默认长度16的数组,默认加载因子为0.75,数组名table
- 使用元素的哈希值对数组的长度求余计算出应存入的位置
- 判断当前位置是否为null,如果是null直接存入
- 如果不为null,表示有元素,则调用equals方法比较
- 相等,则不存;不相等,则存入数组
1. JDK 8之前,新元素存入数组,占老元素位置,老元素挂下面 链表
2. JDK 8开始之后,新元素直接挂在老元素下面 链表
- 相等,则不存;不相等,则存入数组
哈希表是一种增删改查数据性能都较好的结构。
根据数据对应的hash值,我们可以快速定位,所以查很快
增删改由于这个虽然是数组,但是可以允许有空元素的存在再加上链表的特征,所以也很快
无序
这是有一个计算方法的,所以无序
不重复
因为重复的不存,不重复的挂链表
无索引
元素是无序的,自然就不支持索引,没法确定索引
如果数组快占满了,会出什么问题
链表会过长,导致查询性能降低
16 * 0.75 = 12 当数组占满了12的时候就会扩容 0.75是加载因子
哈希表
JDK8之前,哈希表 = 数组+链表
JDK8开始,哈希表 = 数组+链表+红黑树
JDK8开始,当链表长度超过8,且数组长度>=64时,自动将链表转成红黑树
树
一个节点包括一下内容
- 父节点的地址值
- 值
- 左节点的地址值
- 右节点的地址值
如果没有父节点或者没有 左右节点,那么这些节点对应的位置是null
度
每一个节点的子节点的数量
二叉树中任意节点的度为<=2
树高
树的总层数
根节点
最顶层的节点
左子树
右子树
二叉查找树
左节点比根节点小
右节点比根节点大
我们经常使用这个二叉查找树来进行查找节点
二叉树的遍历方式
前序遍历 从跟节点开始 左子节点,右子节点的顺序遍历
当前,左 ,右的遍历方式
中序遍历 我们先遍历最左边的节点(即最左边的叶子节点),等这个节点遍历完之后我们就往上一层,如果有右节点,那么先观察它有没有左节点,如果有的话那么我们就遍历左节点
记住关键点,一切都是以左节点为先
后序遍历
左,右,当前节点
层次遍历
一层一层的遍历
平衡二叉树
平衡二叉树的特点
二叉树左右两个子树的高度差不超过1
任意节点的左右两个子树都是一颗平衡二叉树
平衡二叉树旋转
旋转触发时机
当添加一个节点之后,该树不再是一颗平衡二叉树
左旋
就是将根节点的右侧往左拉,原先的右子节点变成新的父节点,并把多余的左子节点出让,给已经降级的根节点当右子节点
从添加的节点开始,不断的往父节点中找不平衡的点
平衡右旋
右旋
就是将根节点的左侧往右拉,左子节点变成了新的父节点,并把多余的右子节点出让,给已经降级根节点当左子节点
左右
左右: 当根节点左子树的右子树有节点插入,导致二叉树不平衡
如何旋转: 先在左子树对应的节点位置进行左旋,在对整体进行右旋
我们并不能通过一次旋转来实现这个二叉树的变换
红黑树
简单路径其实综合来说就是,不能回头
我们通过第五条规则来设定这个红色节点的数量
添加节点的规则
默认添加的节点是红色的,这样的话效率高
叔叔节点就是父节点的兄弟节点
根据这个操作来说,是不难的
红黑树是一种增删改查数据性能相对都较好的结构
去重复
HashSet集合默认不能对内容一样的两个不同对象去重复!
比如内容一样的两个学生对象存入到HashSet集合中去 , HashSet集合是不能去重复的!
如何让HashSet集合能够实现对内容一样的两个不同对象也能去重复???
结论:如果希望Set集合认为2个内容一样的对象是重复的,
必须重写对象的hashCode()和equals()方法
IDEA里有快速构造方法
linkset
有序、不重复、无索引。
Set<Integer> set = new LinkedHashSet<>();
set.add(90);
set.add(80);
set.add(70);
set.add(70);
System.out.println(set);
[90, 80, 70]
底层原理
依然是基于哈希表(数组、链表、红黑树)实现的。
但是,它的每个元素都额外的多了一个双链表的机制记录它前后元素的位置。
其实也是一样的,存放的位置和hashset是一样的,但是每一个元素都有一个前置节点和后置节点,可以确定这个节点的下一个元素,和这个节点的上一个元素,这样我们就能够知道这个哈希表中的第一个元素和后一个元素.
里面记录的信息更多,这样也会导致它更占内存
treeset
排序、不重复、无索引。会对你上传的数据,会自动进行排序,升序排序
Set<Integer> set = new TreeSet<>();
set.add(90);
set.add(80);
set.add(70);
set.add(70);
System.out.println(set);
[80, 70, 90]
底层是基于红黑树实现的排序。
对于数值类型:Integer , Double,默认按照数值本身的大小进行升序排序。
对于字符串类型:默认按照首字符的编号升序排序。
对于自定义类型如Student对象,TreeSet默认是无法直接排序的。
我们需要自己自定义比较器
第一种方式是在学生类中添加接口
public class Student implements Comparable<Student>
@Override
public int compareTo(Student o) {
//如果认为左边对象大于右边对象返回正整数
//如果认为左边对象小于右边对象返回负整数
//如果认为左边对象等于右边对象返回0 相等的话,就认为这个对象不存在,所以我们要在添加另一个规则
//左边对象就是调用对象
//按照年龄升序排序
int num =0;
num = this.age-o.age;
num = num==0?(int)(this.height-o.height):num;
num = num==0? this.name.compareTo(o.name):num;
return num;
}
}
第二种方式是用匿名内部类
Set<Student> s = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return 0;
}
});
注意点
接口是
Comparable<Student>
接口是
Comparator<Student>
总结
1、如果希望记住元素的添加顺序,需要存储重复的元素,又要频繁的根据索引查询数据?
用ArrayList集合(有序、可重复、有索引),底层基于数组的。(常用)
2、如果希望记住元素的添加顺序,且增删首尾数据的情况较多?
用LinkedList集合(有序、可重复、有索引),底层基于双链表实现的。
3. 如果不在意元素顺序,也没有重复元素需要存储,只希望增删改查都快?
用HashSet集合(无序,不重复,无索引),底层基于哈希表实现的。 (常用)
4.如果希望记住元素的添加顺序,也没有重复元素需要存储,且希望增删改查都快?
用LinkedHashSet集合(有序,不重复,无索引), 底层基于哈希表和双链表。
5. 如果要对元素进行排序,也没有重复元素需要存储?且希望增删改查都快?
用TreeSet集合,基于红黑树实现。
集合的并发修改异常
使用迭代器遍历集合时,又同时在删除集合中的数据,程序就会出现并发修改异常的错误
Iterator<String> iter = list.iterator();
while (iter.hasNext()){
String name = iter.next();
if(name.contains("李")){
list.remove(name);
}
}
这是因为:删除的时候下标会继续向后所以会漏删
for (int i = 0; i < list.size(); i++) {
String name = list.get(i);
if(name.contains("李")){
list.remove(name);
}
}
System.out.println(list);
[王麻子, 小李子, 李爱花, 张全蛋, 晓李, 李玉刚]
[王麻子, 李爱花, 张全蛋, 李玉刚]
for (int i = 0; i < list.size(); i++) {
String name = list.get(i);
if(name.contains("李")){
list.remove(name);
i--;
}
}
System.out.println(list);
[王麻子, 小李子, 李爱花, 张全蛋, 晓李, 李玉刚]
[王麻子, 张全蛋]
由于增强for循环遍历集合就是迭代器遍历集合的简化写法,因此,使用增强for循环遍历集合,又在同时删除集合中的数据时,程序也会出现并发修改异常的错误
lamda foreach表达式本身其实也是利用增强for循环
怎么保证遍历集合同时删除数据时不出bug?
使用迭代器遍历集合,但用迭代器自己的删除方法删除数据即可。
迭代器自带的
iter.remove();
删除当前的元素
如果能用for循环遍历时:可以倒着遍历并删除;或者从前往后遍历,但删除元素后做i --操作。
Iterator<String> iter = list.iterator();
while (iter.hasNext()){
String name = iter.next();
if(name.contains("李")){
iter.remove();
}
}
System.out.println(list);
集合进阶
可变参数
就是一种特殊形参,定义在方法、构造器的形参列表里,格式是:数据类型…参数名称;
传递不定数量的某种类型的参数
public static void test(int ...nums){
}
可变参数的特点和好处
特点:可以不传数据给它;可以传一个或者同时传多个数据给它;也可以传一个数组给它。
好处:常常用来灵活的接收数据。
其实就是一个数组
注意事项
一个形参列表中,只能有一个可变参数,无论类型,都只能有一个
可变参数必须放在形参列表的最后面
public class test01 {
public static void main(String[] args) {
test("kehao",1,2,3,4,5,6);
}
public static void test(String name,int ... num){
System.out.println(num.length);
System.out.println(name);
System.out.println(Arrays.toString(num));
}
}
collections
这个sort是只能对默认的整形规则来进行排序,但是对于我们自己自定义的规则,我们并不能
斗地主的做牌,洗牌,发牌,排序,看牌
本身我的做法有很大问题,在面对这汇总类型固定,数量固定的牌组构建,我并没有想到直接利用数组来进行构建,而是用了多层循环来遍历,导致这个代码看起来臃肿不堪
public Room() {
//本身在构建对象的时候我们就可以自己产生一副牌
String[] color = new String[]{"红桃","方片","黑桃","梅花"};
List<Card> temp = new ArrayList<>();
//从3到10
for (int i=3;i<11;i++){
for (String s : color) {
Card card = new Card(String.valueOf(i),s,i-2);
temp.add(card);
}
}
//3 到 j
for (char c = 'J';c<='K';c++){
for (String s : color) {
Card card = new Card(String.valueOf(c),s,(int)(c)-65);
temp.add(card);
}
}
for (int i=1;i<=2;i++){
for (String s : color) {
Card card = new Card(String.valueOf(i),s,i+11);
temp.add(card);
}
}
Card joker = new Card("大王","红色",15);
temp.add(joker);
Card joker1 = new Card("小王","黑色",14);
temp.add(joker1);
this.cards.addAll(temp);
}
较为合适的代码
public Room() {
//本身在构建对象的时候我们就可以自己产生一副牌
String[] color = new String[]{"红桃","方片","黑桃","梅花"};
String[] points = new String[]{"3","4","5","6","7","8","9","10","J","Q","K","J","2"};
//从3到10
int size=0;
for (String point : points) {
size++;
for (String s : color) {
Card c= new Card(point,s,size);
cards.add(c);
}
}
Card joker = new Card("大王","红色",++size);
Card joker1 = new Card("小王","黑色",++size);
Collections.addAll(cards,joker,joker1);
}
Map集合
Map集合是双列集合
Map集合称为双列集合,格式:{key1=value1 , key2=value2 , key3=value3 , …}, 一次需要存一对数据做为一个元素.
Map集合的每个元素“key=value”称为一个键值对/键值对对象/一个Entry对象,Map集合也被叫做“键值对集合”
Map集合的所有键是不允许重复的,但值可以重复,键和值是一一对应的,每一个键只能找到自己对应的值
Map集合的键不能重复,Map集合的值可以重复
Map集合在什么业务场景下使用
{商品1=2 , 商品2=3 , 商品3 = 2 , 商品4= 3}
需要存储一一对应的数据时,就可以考虑使用Map集合来做
Map集合体系的特点
注意:Map系列集合的特点都是由键决定的,值只是一个附属品,值是不做要求的
HashMap(由键决定特点): 无序、不重复、无索引; (用的最多)
LinkedHashMap (由键决定特点):由键决定的特点:有序、不重复、无索引。
TreeMap (由键决定特点):按照键大小默认升序排序、不重复、无索引。
经典代码
Map<String,Integer> map = new HashMap<>();
Map<String,Integer> map = new HashMap<>();
map.put("黑丝",2);
map.put("白丝",1);
map.put("白丝",3); //后面重复的数据会覆盖前面的数据
map.put("渔网",3);
System.out.println(map);
map集合的常用方法
因为这个键值是无序,无索引,不重复,所以自然要将这个放到这个set集合中0
因为值是可以重复的,所以把这个值放到这个collection集合中
Set<String> keys = map.keySet();
System.out.println(keys);
Collection<Integer> values = map.values();
System.out.println(values);
将一个集合的元素倒入到另一个集合中去
map集合的遍历方式
键找值
我们利用keyset方法来获得所有键的集合,然后根据这个getkey获得对应的值
键值对
本质是利用这个增强for循环来进行遍历,但是对于增强for循环,我们要有其对那个的数据类型,为了方便遍历,java封装了一个entry对象,我们可以通过这个来进行遍历
Set< Map.Entry<String, Double > entries = map.entrySet();
for (Map.Entry<String, Double> entry : entries) {
tring key = entry.getKey();
double value = entry.getValue();
System.out.println(key + "====>" + value);
}
lambda表达式
查看源码就是这个foreach 使用这个匿名内部类,然后内部的实现方式是通过第二种的entry方式来进行实现的.
map.forEach((k,v)->{
System.out.println(k+"-->"+v);
});
只要是存储意义对应的数据的时候,我们就可以考虑用map集合
Map的三个常见实现类
HashMap
HashMap集合的底层原理
HashMap跟HashSet的底层原理是一模一样的,都是基于哈希表实现的。
实际上:原来学的Set系列集合的底层就是基于Map实现的,只是Set集合中的元素只要键数据,不要值数据而已。
public HashSet() {
map = new HashMap<>();
}
哈希表
- JDK8之前,哈希表 = 数组+链表
- JDK8开始,哈希表 = 数组+链表+红黑树
- 哈希表是一种增删改查数据,性能都较好的数据结构。
HashMap集合是一种增删改查数据,性能都较好的集合
但是它是无序,不能重复,没有索引支持的(由键决定特点
HashMap的键依赖hashCode方法和equals方法保证键的唯一
如果键存储的是自定义类型的对象,可以通过重写hashCode和equals方法,这样可以保证多个对象内容一样时,HashMap集合就能认为是重复的。
LinkedMap
底层数据结构依然是基于哈希表实现的,只是每个键值对元素又额外的多了一个双链表的机制记录元素顺序(保证有序)。
实际上:原来学习的LinkedHashSet集合的底层原理就是LinkedHashMap。
TreeMap
特点:不重复、无索引、可排序(按照键的大小默认升序排序,只能对键排序)
原理:TreeMap跟TreeSet集合的底层原理是一样的,都是基于红黑树实现的排序
TreeMap集合同样也支持两种方式来指定排序规则
让类实现Comparable接口,重写比较规则。
TreeMap集合有一个有参数构造器,支持创建Comparator比较器对象,以便用来指定比较规则
Stream
处理方法就是
- 获取流
- 中间处理
- 流的终结
- filter是限制条件
- foreach是进行遍历
常见数据类型获取Stream的方法
list
List<String> list = new ArrayList<>();
Collections.addAll(list,"刘德华","古天乐","德玛西亚","艾欧尼亚","德云色");
Stream<String> stream = list.stream();
stream.filter(s->s.contains("德")).forEach(System.out::println);
set
Set<String> set = new HashSet<>();
Collections.addAll(set,"刘德华","古天乐","德玛西亚","艾欧尼亚","德云色");
Stream<String> stream1 = set.stream();
stream1.filter(s->s.length()==3).forEach(System.out::println);
map
Map<String, Double> map = new HashMap<>();
map.put("古力娜扎",172.3);
map.put("迪丽热巴",168.3);
map.put("马尔扎哈",166.3);
map.put("卡尔扎巴",168.3);
//由于map集合不属于collection,所以我们不能直接使用这个Stream流
Set<String> set1 = map.keySet();
Stream<String> stream2 = set1.stream();
Collection<Double> values = map.values();
Stream<Double> stream3 = values.stream();
Set<Map.Entry<String, Double>> entries = map.entrySet();
Stream<Map.Entry<String, Double>> stream4 = entries.stream();
stream4.filter(s->s.getKey().contains("巴")).forEach(s-> System.out.println(s));
数组
String[] views = {"五台山","玄武湖","故宫","蔡明园","夫子庙","灵隐寺","西湖"};
Stream<String> stream5 = Arrays.stream(views);
Stream<String> views1 = Stream.of(views);
常见的中间方法
间方法指的是调用完成后会返回新的Stream流,可以继续使用(支持链式编程)
比较难以理解的是
sort
对于我们重写的这个sort方法,当我们简略缩写的时候我们
stream.filter(s->s>30).sorted((Double o1, Double o2)-> (int)(o2-o1)).forEach(s-> System.out.println(s));
这个return是不在使用的
distinct,如果是我们自己自定义的对象,如果我们向去除重复的元素我们可以通过重写对象中的equals和hashcode方法来进行书写代码
map
map就是让这个流变成它给出的元素的流,比如说一个对象流我们只需要用其中一个属性值,那么我们就可以用这个
常用的终结方法
max和min都可以重写匿名内部类
最后这个返回的是optionnal类型的对象,因此我们并不能直接获取,我们要在其后面再加入这个get来实现
Student student = students.stream().min(((o1, o2) -> o2.getAge() - o1.getAge())).get();
System.out.println(student);
收集Stream流:就是把Stream流操作后的结果转回到集合或者数组中去返回。
就是我们处理的结果,传递到这个集合和数组容器之中去
Stream流:方便操作集合/数组的手段; 集合/数组:才是开发中的目的。
List<Student> collect = students.stream().filter(s -> s.getAge() > 30).collect(Collectors.toList());
System.out.println(collect);
流的注意事项
流只能收集一次,不能重复使用
本文作者:TranquilGlow
本文链接:https://www.cnblogs.com/xuehaiqiule/p/17621618.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步