Stream流常用方法大全及其优劣
目录
Stream流简介
Stream流常用方法大全
forEach遍历
filter过滤
distinct去重
limit截取
skip跳过
sorted排序
max,min,count聚合
reduce统计
List结构转换Map结构
List对象转List
List对象转List
Stream流特点及优缺点
特点
优缺点
Stream流简介
为了简化集合类操作,JDK1.8出现的一种操作——Stream流,其不是一种数据结构,不保存数据,它只是在原数据集上定义了一组操作。这些操作是惰性的,即每当访问到流中的一个元素,才会在此元素上执行这一系列操作。Stream不保存数据,故每个Stream流只能使用一次。stream流的方法有很多中,大致分为延迟方法和终结方法:
- 延迟方法 :返回值类型仍然是 Stream 接口自身类型的方法,因此支持链式调用。(除了终结方法外,其余方法均为延迟方法。)
- 终结方法 :返回值类型不再是 Stream 接口自身类型的方法,因此不再支持类似 StringBuilder 那样的链式调用。终结方法包括 count 和 forEach 方法
Stream流常用方法大全
- forEach遍历
- filter过滤
- distinct去重
- limit截取
- skip跳过
- sorted排序
- max,min最值
- reduce统计
- List结构转换Map结构
- List<Object>对象转List<String>
- List<Object>对象转List<Object>
forEach遍历
终结方法,遍历之后就不能继续调用Stream流中的其他方法
public static void main(String[] args) {//获取一个Stream流Stream<String>stream= Stream.of("张三","李四","王五","赵六");//使用Stream流的方法forEach对stream流中的数据遍历stream.forEach((String name)->{System.out.println(name);});
}
filter过滤
public static void main(String[] args) {//创建一个Stream流Stream<String> stream = Stream.of("张三", "李四", "王五", "赵六1", "刘老七");//单条件过滤Stream<String> stream1 = stream.filter((String name) -> {return name.startsWith("刘");});//多条件过滤List<String> stream2 = stream.filter((String name) -> {if(name.length()>=3 && name.equals("刘老七")){return true;}return false;}).collect(Collectors.toList);//遍历stream1stream1.forEach((name)-> System.out.println(name));//输出stream2System.out.println(stream2)}
distinct去重
public static void main(String[] args) {//创建一个Stream流Stream<String> stream = Stream.of("张三", "张三","张三","李四", "王五", "赵六1", "刘老七");//去重List<String> stream1 = stream().distinct().collect(Collectors.toList());//输出stream1System.out.println(stream1)}
limit截取
limit(long maxSize);参数是一个long型,如果集合当前长度大于参数则进行截取,否则不进行操作
public static void main(String[] args) {//创建一个Stream流Stream<String> stream = Stream.of("张三", "张三","张三","李四", "王五", "赵六1", "刘老七");//去重List<String> list = stream().distinct().collect(Collectors.toList());//截取去重后的前2个元素list = list.stream().limit(2).collect(Collectors.toList();//输出stream1System.out.println(list)}
skip跳过
skip(long n)如果流的当前长度大于n,则跳过前n个,否则将会得到一个长度为0的空流
public static void main(String[] args) {//创建一个Stream流Stream<String> stream = Stream.of("张三", "张三","张三","李四", "王五", "赵六1", "刘老七");//去重List<String> list = stream().distinct().collect(Collectors.toList());//跳过去重后的前2个元素list = list.stream().skip(2).collect(Collectors.toList());//输出stream1System.out.println(list)}
sorted排序
public static void main(String[] args) {List<Test> list = new ArrayList<>();list.add(new Test("张三",23,new BigDecimal("3000"),new BigDecimal("1.1")));list.add(new Test("李四",24,new BigDecimal("2800"),new BigDecimal("1.2")));list.add(new Test("王五",22,new BigDecimal("3200"),new BigDecimal("1.3")));//根据年龄从大到小排序list = list.stream().sorted(Comparator.comparing(Test::getAge).reversed()).collect(Collectors.toList());list.forEach(System.out::println); }
max,min,count聚合
public static void main(String[] args) {List<Test> list = new ArrayList<>();list.add(new Test("张三",23,new BigDecimal("3000"),new BigDecimal("1.1")));list.add(new Test("李四",24,new BigDecimal("2800"),new BigDecimal("1.2")));list.add(new Test("王五",22,new BigDecimal("3200"),new BigDecimal("1.3")));//获取年龄最大的人Test maxPeople = list.stream().max(Comparator.companing(Test::getAge)).get();//获取年龄最小的人Test minPeople = list.stream().min(Comparator.companing(Test::getAge)).get();//获取数量long count = list.stream().filter(x -> x > 5).count();}
reduce统计
public static void main(String[] args) {List<Test> testList = new ArrayList<Test>();testList.add(new Test("小明",23,new BigDecimal("3000"),new BigDecimal("1.1")));testList.add(new Test("小红",24,new BigDecimal("2800"),new BigDecimal("1.2")));testList.add(new Test("小兰",22,new BigDecimal("3200"),new BigDecimal("1.3")));//统计年龄总和int totalAge =testList.stream().mapToInt(Test::getAge).sum();//统计工资总和BigDecimal totalSalary = testList.stream().map(Test::getSalary)//统计工资乘以各自系数的总和(向上保留两位)BigDecimal totalRatioSalary = testList.stream().map(s->s.getSalary().multiply(s.getRatio()).setScale(2,BigDecimal.ROUND_HALF_UP)).reduce(BigDecimal.ZERO,BigDecimal::add);}
List结构转换Map结构
public static void main(String[] args) {List<Test> testList = new ArrayList<Test>();testList.add(new Test("张三",23,new BigDecimal("3000"),new BigDecimal("1.1")));testList.add(new Test("李四",24,new BigDecimal("2800"),new BigDecimal("1.2")));testList.add(new Test("王五",22,new BigDecimal("3200"),new BigDecimal("1.3")));//根据姓名转map,map的key为nameMap<String, Test> nameMap= testList.stream().collect(Collectors.toMap(Test::getName, Test -> Test);System.out.println(map);}
List<Object>对象转List<String>
public static void main(String[] args) {List<Test> testList = new ArrayList<Test>();testList.add(new Test("张三",23,new BigDecimal("3000"),new BigDecimal("1.1")));testList.add(new Test("李四",24,new BigDecimal("2800"),new BigDecimal("1.2")));testList.add(new Test("王五",22,new BigDecimal("3200"),new BigDecimal("1.3")));//获取姓名集合List<String> nameList = testList.stream().map(Test::getName()).collect(Collectors.toList());System.out.println("value:"+nameList);}
List<Object>对象转List<Object>
public static void main(String[] args) {List<People> peopleList = new ArrayList<People>();peopleList.add(new People("张三",23,new BigDecimal("3000"),new BigDecimal("1.1")));peopleList.add(new People("李四",24,new BigDecimal("2800"),new BigDecimal("1.2")));peopleList.add(new People("王五",22,new BigDecimal("3200"),new BigDecimal("1.3")));//对象转对象List<Student> studentList = peopleList.stream().map(s->{return new Student(s.getName(),s.getAge());}).collect(Collectors.toList());System.out.println("value:"+studentList);}
Stream流特点及优缺点
特点
- stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果。
- stream不会改变数据源,通常情况下会产生一个新的集合或一个值。
- stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行。
- stream只能遍历一次,并且采用内部迭代的方式
优缺点
优点:
- 无存储
- 函数式风格
- 惰性求值
- 无需上界
- 代码优雅简洁
缺点:
- 性能在小规模的情况下不如Iterator
- 对于传统 iterator (for-loop) 比 stream(JDK8) 迭代性能要高,尤其在小数据量的情况下;
- 在多核情景下,对于大数据量的处理,parallel stream 可以有比 iterator 更高的迭代处理效率;
- 单核cpu不推荐使用
- stream中含自动装箱拆箱,最好转成对应的数值流,减少自动装箱、拆箱造成性能的损失