不可变集合的概念
不可变集合,就是不可被修改的集合
集合的数据项在创建的时候提供,并且在整个生命周期中都不可改变。否则报错
创建不可变集合的原因
如果某个数据不能被修改,把它防御性地拷贝到不可变集合中是个很好的实践
或者当集合对象被不可信的库调用时,不可变形式是安全的
如何创建一个不可变集合(JDK9开始才支持)
Stream流
案例:体验Strenm流
基础代码
package com.itliuxue.d2_stream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
//初步体验Stream的方便与快捷
public class StreamTest {
public static void main(String[] args) {
List<String> name = new ArrayList<>();
Collections.addAll(name,"张三丰","张无忌","赵敏","周芷若","张强");
System.out.println(name);
//找姓张的名字
List<String> zhangList = new ArrayList<>();
for (String names : name) {
if(names.startsWith("张")){
zhangList.add(names);
}
}
System.out.println(zhangList);
//找长度为三的名字
List<String> zhangTreeList = new ArrayList<>();
for (String s : zhangList) {
if(s.length() == 3){
zhangTreeList.add(s);
}
}
System.out.println(zhangTreeList);
}
}
使用Stream流代码
package com.itliuxue.d2_stream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
//初步体验Stream的方便与快捷
public class StreamTest {
public static void main(String[] args) {
List<String> name = new ArrayList<>();
Collections.addAll(name,"张三丰","张无忌","赵敏","周芷若","张强");
System.out.println(name);
// List<String> zhangList = new ArrayList<>();
// for (String names : name) {
// if(names.startsWith("张")){
// zhangList.add(names);
// }
// }
// System.out.println(zhangList);
//
//
// List<String> zhangTreeList = new ArrayList<>();
// for (String s : zhangList) {
// if(s.length() == 3){
// zhangTreeList.add(s);
// }
// }
// System.out.println(zhangTreeList);
name.stream().filter(s->s.startsWith("张")).filter(s->s.length()==3).forEach(s-> System.out.println(s));
}
}
总结
1.stream流的作用
简化集合,数组操作的API。结合了Lambda表达式
2.说说Stream流的思想和使用不骤
先得到集合或者数组的Stream流(就是一根传送带)
把元素放上去
然后就用这个Stream流简化的API来方便的操作元素
Stream流的三类方法
Stream流的获取
package com.itliuxue.d2_stream;
import java.util.*;
import java.util.stream.Stream;
public class StreamDemo02 {
public static void main(String[] args) {
//---------------Collection集合获取流------------------
Collection<String> list = new ArrayList<>();
Stream<String> s = list.stream();
//---------------Map集合获取流-------------------
Map<String,Integer> map = new HashMap();
//键流
Stream<String> ks = map.keySet().stream();
//值流
Stream<Integer> vs = map.values().stream();
//键值对流
Stream<Map.Entry<String, Integer>> keyAndValueStream = map.entrySet().stream();
//--------------数组获取流--------------
String[] name = {"赵敏","小昭","灭绝","周芷若"};
Stream<String> nameStream = Arrays.stream(name);
Stream<String> nameStream2 = Stream.of(name);
}
}
总结
Stream流的常用API
学生类
package com.itliuxue.d2_stream;
public class Student {
private String name;
public Student() {
}
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
'}';
}
}
package com.itliuxue.d2_stream;
import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
public class StreamDemo03 {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
Collections.addAll(names,"张无忌","周芷若","赵敏","张强","张三丰","张三丰");
names.stream().filter(s -> s.startsWith("张")).forEach(s -> System.out.println(s));
//张无忌
//张强
//张三丰
//张三丰
long count = names.stream().filter(s -> s.length() == 3).count();
System.out.println(count);
//4
//limit取前几个元素
// names.stream().filter(s -> s.startsWith("张")).limit(2).forEach(s -> System.out.println(s));
names.stream().filter(s -> s.startsWith("张")).limit(2).forEach(System.out::println);
//skip跳过前几个元素
names.stream().filter(s -> s.startsWith("张")).skip(2).forEach(System.out::println);
//Map加工方法:第一个参数是原材料->第二个参数是加工后的结果
//给集合元素前面加一个:中国的:
names.stream().map(s -> "中国的" + s).forEach(System.out::println);
//构造器引用 方法引用
// 中国的张无忌
// 中国的周芷若
// 中国的赵敏
// 中国的张强
// 中国的张三丰
// 中国的张三丰
//将所有名称都加工成一个学生对象
// names.stream().map(s -> new Student(s)).forEach(System.out::println);
names.stream().map(Student::new).forEach(System.out::println);
//Student{name='张无忌'}
//Student{name='周芷若'}
//Student{name='赵敏'}
//Student{name='张强'}
//Student{name='张三丰'}
//Student{name='张三丰'}
//合并流
Stream<String> s1 = names.stream().filter(s -> s.startsWith("张"));
Stream<String> s2 = Stream.of("Java1","Java2");
//public static <T> Stream<T> concat(@NotNull Stream<? extends T> a,
// @NotNull Stream<? extends T> b)
Stream<String> s3 = Stream.concat(s1,s2);
// s3.forEach(s -> System.out.println(s));
//张无忌
//张强
//张三丰
//张三丰
//Java1
//Java2
//去重复
s3.distinct().forEach(s -> System.out.println(s));
//张无忌
//张强
//张三丰
//Java1
//Java2
}
}
Stream流的终结方法
注意:终结操作方法,调用完成后流就无法使用了,原因是不会返回Stream了
Stream流的案例应用
员工类
package com.itliuxue.d2_stream;
public class Employee {
private String name;
private char sex;
private double salary;
private double bonus;
private String punish;
public Employee() {
}
public Employee(String name, char sex, double salary, double bonus, String punish) {
this.name = name;
this.sex = sex;
this.salary = salary;
this.bonus = bonus;
this.punish = punish;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
public String getPunish() {
return punish;
}
public void setPunish(String punish) {
this.punish = punish;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", sex=" + sex +
", salary=" + salary +
", bonus=" + bonus +
", punish='" + punish + '\'' +
'}';
}
}
优秀员工类
package com.itliuxue.d2_stream;
public class TopperFormer {
private String name;
private double money;
public TopperFormer() {
}
public TopperFormer(String name, double money) {
this.name = name;
this.money = money;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
@Override
public String toString() {
return "TopperFormer{" +
"name='" + name + '\'' +
", money=" + money +
'}';
}
}
package com.itliuxue.d2_stream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Stream;
public class StreamTest02 {
public static double allMoney;
public static double allMoney2;
public static void main(String[] args) {
List<Employee> one = new ArrayList<>();
one.add(new Employee("猪八戒",'男',30000,25000,"null"));
one.add(new Employee("孙悟空",'男',25000,1000,"顶撞上司"));
one.add(new Employee("沙僧",'男',20000,20000,"null"));
one.add(new Employee("白龙马",'男',20000,25000,null));
List<Employee> two = new ArrayList<>();
two.add(new Employee("武松",'男',15000,9000,"null"));
two.add(new Employee("李逵",'男',20000,10000,null));
two.add(new Employee("西门庆",'男',50000,100000,"被打"));
two.add(new Employee("潘金莲",'女',3500,1000,"被打"));
two.add(new Employee("武大郎",'男',20000,0,"下毒"));
//开发一部最高规则的员工
//指定大小规则
TopperFormer t = one.stream().max((e1, e2) -> Double.compare(e1.getSalary() + e1.getBonus(), e2.getSalary() + e2.getBonus()))
.map(e -> new TopperFormer(e.getName(), e.getSalary() + e.getBonus())).get();
System.out.println(t);
//统计平均工资
one.stream().sorted((e1,e2)->Double.compare(e1.getSalary()+ e1.getBonus(), e2.getSalary()+ e2.getBonus()))
.skip(1).limit(one.size()-2).forEach(e->{
//求出总和
allMoney += (e.getSalary()+e.getBonus());
});
System.out.println("开发一部的平均工资是"+allMoney / (one.size()-2));
//合并两个集合流,再统计
Stream<Employee> s1 = one.stream();
Stream<Employee> s2 = two.stream();
Stream<Employee> s3 = Stream.concat(s1,s2);
s3.sorted((e1,e2)->Double.compare(e1.getSalary()+ e1.getBonus(), e2.getSalary()+ e2.getBonus()))
.skip(1).limit(one.size() + two.size() - 2).forEach(e->{
//求出总和
allMoney2 += (e.getSalary()+e.getBonus());
});
//BigDecimal处理精度问题
BigDecimal a = BigDecimal.valueOf(allMoney2);
BigDecimal b = BigDecimal.valueOf(one.size()+ two.size()-2);
System.out.println("开发部的平均工资是"+a.divide(b,2, RoundingMode.HALF_UP));
}
}
收集Stream流
package com.itliuxue.d2_stream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
//收集Stream流的数据到集合或者数组中去
public class StreamDemo04 {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
Collections.addAll(names,"张无忌","周芷若","赵敏","张强","张三丰","张三丰");
Stream<String> s1 = names.stream().filter(s -> s.startsWith("张"));
List<String> zhangList = s1.collect(Collectors.toList());
System.out.println(zhangList);
Stream<String> s2 = names.stream().filter(s -> s.startsWith("张"));
Object[] arrs = s2.toArray();
System.out.println("数组内容"+ Arrays.toString(arrs));
}
}
流只能使用使用一次