一、描述

Stream流提供了筛选与切片、映射、排序、匹配与查找、归约、收集等功能

筛选与切片:

  filter:接收lambda,从流中排除某些元素

  limit(n):截断流,使其元素不超过n

  skip(n):跳过元素,返回一个扔掉了n个元素的流,如果流中元素数不超过n,则返回一个空流,与limit(n)互补

  distinct:筛选,通过流所生成的元素的hashCode和equals去重

映射:

  map:接收一个lambda,将元素转换成其他形式或提取信息,接收一个函数作为参数,该函数会被应用到每一个元素上,并将其映射成一个新的元素

  flatMap:接收一个函数作为参数,将其中的每个值都替换成另一个流,然后把所有流连接成一个流

排序:

  sorted()自然排序:comparable

  sorted(Comparator com)定制排序:comparator

查找与匹配:

  allMatch:检查是否匹配所有元素

  anyMatch:检查是否至少匹配一个元素

  noneMatch:检查是否所有都不匹配

  findFirst:返回第一个元素

  findAny:返回当前流中任意元素

  count:返回当前流中元素个数

  max:返回当前流中最大值

  min:返回流中最小值

归约:

  reduce(T identity, BinaryOperator) / reduce(BinaryOperator) 可以将流中元素反复结合起来,得到一个流

收集:

  collect:将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总的方法

二、Strem语法

  Stream分为创建流、中间操作和终止操作三个部分

  (1)创建流有三种方式:

  第一种是使用通过Collection系列集合提供Strem()(串行流)和parellelStream()(并行流)得到一个流对象

        //1、通过Collection系列集合提供Strem()(串行流)和parellelStream()(并行流)得到一个流对象
List list = new ArrayList();
Stream stream = list.stream();
Stream stream1 = list.parallelStream();

  第二种是通过数组中的静态方法stream()获取数组流

        //2、通过数组中的静态方法stream()获取数组流
String[] arr = new String[];
Stream stream2 = Arrays.stream(arr);

  第三种是通过Stream中的静态方法of()创建

        List list = new ArrayList();//3、通过Stream中的静态方法of()创建
Stream stream3 = Stream.of(list);

  除了上述三种,还有一种无限流的创建

  下面的迭代表示从0开始,每次加2,无限循环;生成就会无限生成随机数

        //无限流------迭代
Stream stream4 = Stream.iterate(, x->x+);
//无限流------生成
Stream stream6 = Stream.generate(()->Math.random());

  (2)中间操作

  中间操作就是筛选切片、映射等都属于中间操作,操作后仍然返回一个流,以上面的无限流--迭代为例,可以使用截断流limit不让其无限循环,只要前10个

        Stream stream5 = stream4.limit();

  (3)终止操作,将流对象转换成数据对象的操作,以上述中间操作为例,加循环输出

        //加中间操作的终止操作
stream4.limit().forEach(System.out::println);

  输出结果:0 2 4

三、中间操作详解

  Stream的操作主要就是中间操作如何处理,接下来详细说明中间操作   

1、筛选与切片

为了代码演示需要,先创建一个Student类,和一个状态的枚举类

    public enum Status{
FREE,
BUSY,
VOCATION
} class Student{
private String name;
private Integer age;
private Status status; public Student(String name,Integer age){
this.name = name;
this.age = age;
} public Student(String name,Integer age, Status status){
this.name = name;
this.age = age;
this.status = status;
} public String getName() {
return name;
} public Integer getAge() {
return age;
} public Status getStatus(){
return status;
} public String toString(){
return JSON.toJSONString(this);
} /*public int hashCode(){
int result = 1;
result = this.getAge().hashCode() + this.getName().hashCode();
return result;
} @Override
public boolean equals(Object obj) {
if(obj instanceof Student){
if(this.name.equals(((Student) obj).getName()) && this.age == ((Student) obj).getAge()){
return true;
}
}else {
return super.equals(obj);
}
return false;
}*/
}

创建一个Student的集合

List<Student> students1 = Arrays.asList(
new Student("lcl1",, Status.BUSY)
,new Student("lcl2",, Status.VOCATION)
,new Student("lcl3",, Status.FREE)
,new Student("lcl4",, Status.FREE)
,new Student("lcl5",, Status.BUSY)
,new Student("lcl6",, Status.FREE)
,new Student("lcl2",, Status.VOCATION));

筛选与切片:

  filter:接收lambda,从流中排除某些元素

  limit(n):截断流,使其元素不超过n

  skip(n):跳过元素,返回一个扔掉了n个元素的流,如果流中元素数不超过n,则返回一个空流,与limit(n)互补

  distinct:筛选,通过流所生成的元素的hashCode和equals去重

下面四个例子,分别对应四个中间操作的处理,操作内容分别为:

  只获取年龄小于10的Student后,将集合中Student对象输出;期望输出对象为:lcl5

  返回年龄大于10的前三个Student对象并输出:期望输出对象为:lcl1,lcl2,lcl3

  跳过两个Student对象后取前三个:期望输出对象为:lcl3,lcl4,lcl5

  输出集合中去重后的list对象:期望输出对象为集合中所有,包括两个lcl2,因为这里的去重操作是根据对象的hashCode和equals去判断是否重复的,由于两个lcl2都是new出来的,因此自然非同一个对象,但是如果我们重新hashCode和equals方法,按照名字和年龄一样,就会返回一样的hash码,且equals返回true(上述Student类中注释了重新的hashCode和equals方法,放开即可),则distinct会输出一个lcl2,下面演示输出按照重写hashCode和equals方法验证

    /**
* 筛选与切片
* filter:接收lambda,从流中排除某些元素
* limit(n):截断流,使其元素不超过n
* skip(n):跳过元素,返回一个扔掉了n个元素的流,如果流中元素数不超过n,则返回一个空流,与limit(n)互补
* distinct:筛选,通过流所生成的元素的hashCode和equals去重
*/
@Test
public void tst2(){
log.info("filter测试==============================");
students1.stream().filter((x)->x.getAge() < ).forEach(System.out::println); //惰性求值:所有中间操作不会做任何处理,只有在终止操作时,才会处理
//内部迭代,StreamAPI自己处理的迭代处理
//短路,只要找到满足的数据后,后面的流程就不再处理
log.info("limit测试==============================");
students1.stream().filter((x)->{log.info("filter");return x.getAge() > ;}).limit().forEach(System.out::println); log.info("skip测试==============================");
students1.stream().skip().limit().forEach(System.out::println); log.info("distinct测试==============================");
students1.stream().distinct().forEach(System.out::println);
}

测试结果:

-- ::57.835  INFO  --- [           main] com.example.jdk8demo.Jdk8StreamDemoTest  : filter测试==============================
{"age":,"name":"lcl6","status":"FREE"}
-- ::58.003 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : limit测试==============================
-- ::58.005 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : filter
{"age":,"name":"lcl1","status":"BUSY"}
-- ::58.005 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : filter
{"age":,"name":"lcl2","status":"VOCATION"}
-- ::58.005 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : filter
{"age":,"name":"lcl3","status":"FREE"}
-- ::58.005 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : skip测试==============================
{"age":,"name":"lcl3","status":"FREE"}
{"age":,"name":"lcl4","status":"FREE"}
{"age":,"name":"lcl5","status":"BUSY"}
-- ::58.006 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : distinct测试==============================
{"age":,"name":"lcl1","status":"BUSY"}
{"age":,"name":"lcl2","status":"VOCATION"}
{"age":,"name":"lcl3","status":"FREE"}
{"age":,"name":"lcl4","status":"FREE"}
{"age":,"name":"lcl5","status":"BUSY"}
{"age":,"name":"lcl6","status":"FREE"}

可以发现,所有的输出都与我们期望的一致,根据测试结果,有两个概念需要说下,就是惰性求值和短路,其实在代码的注释中已经有了,这里结合测试结果再详细说明一下

  惰性求值:测试limit的时候,在中间操作中加了输出filter的操作,但是看测试结果,filter的输出和最终的结果输出一样,也是循环一次输出一次,而非通常想的会把所有的filter输出完之后,再循环输出测试结果,这就是惰性求值,即等输出结果时,在求值,而非过程中就求值

  短路:还是以limit测试为例,在使用filter过滤后,应该还有6个元素符合条件,但是在limit(3)之后,只输出了3个对象,最重要的是,连filter字符串都是只输出了三个,而非6个,这就是因为Stream中间操作的短路操作,即找到满足自己的数据后,就不再处理,这样其实也可以提升效率。

2、映射:

  map:接收一个lambda,将元素转换成其他形式或提取信息,接收一个函数作为参数,该函数会被应用到每一个元素上,并将其映射成一个新的元素

  flatMap:接收一个函数作为参数,将其中的每个值都替换成另一个流,然后把所有流连接成一个流

为了做测试,先创建一个方法,传入一个字符串,返回一个单个字符的Stream流

    public static Stream<Character> filterChaacter(String str){
List<Character> list = new ArrayList<>();
for (Character c : str.toCharArray()) {
list.add(c);
}
return list.stream();
}

demo需求:

  将数据组中的字符串变为大写

  输出所有学生的名字

  将数组中所有的字符串输出为单个字符

    @Test
public void test3(){ log.info("模拟map操作");
List<String> list = Arrays.asList("aaa","bbb","ccc","ddd");
list.stream().map((str)->str.toUpperCase()).forEach(System.out::println);
students1.stream().map(Student::getName).forEach(System.out::println); log.info("模拟多重流操作");
Stream<Stream<Character>> stream = list.stream().map(Jdk8StreamDemoTest::filterChaacter);
stream.forEach(sm -> sm.forEach(System.out::println)); log.info("模拟flatMap操作");
list.stream().flatMap(Jdk8StreamDemoTest::filterChaacter).forEach(System.out::println);
}

  上述代码中,模拟map操作块,即是对前两个demo需求的测试,没什么特别可说的,就是使用map从原有对象中获取我们所需要的对象;这里主要说明一下第三个demo需求,由于新增的filterChaacter方法返回的是一个Stream流,那么使用map的话就会得到一个Stream<Stream<Character>>的多重流,所以输出是,就需要双重循环(如模拟多重流代码块),非常的麻烦,因此就有了flatMap,他直接将返回的Stream流拼接成一个Stream流,这样输出的时候就只需要循环一次即可(如模拟flatMap操作)

  测试结果

AAA
BBB
CCC
DDD
lcl1
lcl2
lcl3
lcl4
lcl5
lcl6
lcl2
-- ::18.557 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : 模拟多重流操作
a
a
a
b
b
b
c
c
c
d
d
d
-- ::18.557 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : 模拟flatMap操作
a
a
a
b
b
b
c
c
c
d
d
d

3、排序:

  sorted()自然排序:comparable

  sorted(Comparator com)定制排序:comparator

    @Test
public void test4(){
//自然排序
Arrays.asList("uio","fghf","dsf","ewre","gffjf","poiklk").stream().sorted().forEach(System.out::println);
//定制排序
students1.stream().sorted((s1,s2)->s1.getAge().compareTo(s2.getAge())).forEach(System.out::println);
//倒序排序
students1.stream().sorted((s1,s2)->-s1.getAge().compareTo(s2.getAge())).forEach(System.out::println);
}

测试结果:

dsf
ewre
fghf
gffjf
poiklk
uio
{"age":,"name":"lcl6","status":"FREE"}
{"age":,"name":"lcl1","status":"BUSY"}
{"age":,"name":"lcl4","status":"FREE"}
{"age":,"name":"lcl5","status":"BUSY"}
{"age":,"name":"lcl2","status":"VOCATION"}
{"age":,"name":"lcl2","status":"FREE"}
{"age":,"name":"lcl3","status":"FREE"}
{"age":,"name":"lcl3","status":"FREE"}
{"age":,"name":"lcl2","status":"VOCATION"}
{"age":,"name":"lcl2","status":"FREE"}
{"age":,"name":"lcl5","status":"BUSY"}
{"age":,"name":"lcl4","status":"FREE"}
{"age":,"name":"lcl1","status":"BUSY"}
{"age":,"name":"lcl6","status":"FREE"}

  这个没什么特别可说的,就是一个排序,空参的方法使用自然排序,传入排序方法的,按照穿的比较器进行排序

4、查找与匹配:

  allMatch:检查是否匹配所有元素

  anyMatch:检查是否至少匹配一个元素

  noneMatch:检查是否所有都不匹配

  findFirst:返回第一个元素

  findAny:返回当前流中任意元素

  count:返回当前流中元素个数

  max:返回当前流中最大值

  min:返回流中最小值

demo需求:

  判断集合中是否状态全为BUSY

  判断集合中是否存在状态为BUSY的数据

  判断集合中是否没有一个状态为BUSY的数据

  按照年龄排序后取第一个

  取任意一个元素

  获取集合中数据总数

  获取年龄最大的Student

  获取年龄最小的Student

    @Test
public void test5(){
log.info("allMatch结果{}",students1.stream().allMatch((e)-> e.getStatus() == Status.BUSY));
log.info("anyMatch结果{}",students1.stream().anyMatch((e)-> e.getStatus() == Status.BUSY));
log.info("noneMatch结果{}",students1.stream().noneMatch((e)-> e.getStatus() == Status.BUSY)); Optional<Student> optionalStudent = students1.stream().sorted((e1, e2)->e1.getAge().compareTo(e2.getAge())).findFirst();
if(optionalStudent.isPresent()) log.info("findFirst结果{}",optionalStudent.get()); Optional<Student> optionalStudent1 = students1.stream().filter((e)->e.getStatus()==Status.FREE).findAny();
if(optionalStudent1.isPresent()) log.info("findAny结果{}",optionalStudent1.get()); log.info("count结果{}",students1.stream().count()); Optional<Student> optionalStudent2 = students1.stream().max((e1,e2)->e1.getAge().compareTo(e2.getAge()));
if(optionalStudent2.isPresent()) log.info("max结果{}",optionalStudent2.get()); Optional<Student> optionalStudent3 = students1.stream().min((e1,e2)->e1.getAge().compareTo(e2.getAge()));
if(optionalStudent3.isPresent()) log.info("min结果{}",optionalStudent3.get());
}

  输出结果:

-- ::39.830  INFO  --- [           main] com.example.jdk8demo.Jdk8StreamDemoTest  : allMatch结果false
-- ::39.832 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : anyMatch结果true
-- ::39.832 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : noneMatch结果false
-- ::39.833 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : findFirst结果{"age":,"name":"lcl6","status":"FREE"}
-- ::39.936 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : findAny结果{"age":,"name":"lcl3","status":"FREE"}
-- ::40.025 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : count结果7
-- ::40.027 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : max结果{"age":,"name":"lcl3","status":"FREE"}
-- ::40.028 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : min结果{"age":,"name":"lcl6","status":"FREE"}

  上述代码示例中,有的地方的返回是个Optional,这个下一篇会说明

5、归约:

  reduce(T identity, BinaryOperator) / reduce(BinaryOperator) 可以将流中元素反复结合起来,得到一个流

demo需求:

  将一个集合中的数据,依次相加求和后再与100求和

  将集合中学生的年龄求和后再加10

    @Test
public void test6(){
List<Integer> list = Arrays.asList(,,,,);
log.info("reduce结果{}",list.stream().reduce(100, (x,y)->x+y));
log.info("reduce计算年龄总和结果{}",students1.stream().map((x)->x.getAge()).reduce(,(x,y)->x+y));
}

  测试结果:

-- ::08.448  INFO  --- [           main] com.example.jdk8demo.Jdk8StreamDemoTest  : reduce结果115
-- ::08.450 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : reduce计算年龄总和结果191

6、收集:

  collect:将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总的方法,可以计算总和,最大值、最小值、平均值、分组、多重分组、分区和字符串操作等

  由于collect的内容比较多,所以分开一个一个说明

  (1)数据收集转换

  demo:

    将所有的名字获取,并添加到集合中

    将所有的名字获取,并添加到特殊集合中,例如HashSet

        List list = students1.stream().map(Student::getName).collect(Collectors.toList());
log.info("收集:collect测试结果{}",JSON.toJSONString(list)); Set set = students1.stream().map(Student::getName).collect(Collectors.toCollection(HashSet::new));
log.info("收集:特殊集合collect测试结果{}",JSON.toJSONString(set));

  测试结果:

-- ::37.478  INFO  --- [           main] com.example.jdk8demo.Jdk8StreamDemoTest  : 收集:collect测试结果["lcl1","lcl2","lcl3","lcl4","lcl5","lcl6","lcl2"]
-- ::37.481 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : 收集:特殊集合collect测试结果["lcl5","lcl6","lcl3","lcl4","lcl1","lcl2"]

  (2)计算总数、总和、最大值、最小值、平均值等数据收集操作

        log.info("收集:collect总数测试结果{}",students1.stream().collect(Collectors.counting()));

        log.info("收集:collect计算年龄平均值测试结果{}",students1.stream().collect(Collectors.averagingInt(Student::getAge)));

        log.info("收集:collect计算年龄总和测试结果{}",students1.stream().collect(Collectors.summarizingInt(Student::getAge)));

        log.info("收集:collect获取年龄最大测试结果{}",students1.stream().collect(Collectors.maxBy((s1,s2)->s1.getAge().compareTo(s2.getAge()))).get());

        log.info("收集:collect获取最小的年龄值测试结果{}",students1.stream().map(Student::getAge).collect(Collectors.minBy((s1,s2)->s1.compareTo(s2))).get());

测试结果:

-- ::37.483  INFO  --- [           main] com.example.jdk8demo.Jdk8StreamDemoTest  : 收集:collect总数测试结果7
-- ::37.484 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : 收集:collect计算年龄平均值测试结果25.
-- ::37.485 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : 收集:collect计算年龄总和测试结果IntSummaryStatistics{count=, sum=, min=, average=25.857143, max=}
-- ::37.488 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : 收集:collect获取年龄最大测试结果{"age":,"name":"lcl3","status":"FREE"}
-- ::37.589 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : 收集:collect获取最小的年龄值测试结果8

(3)分组

  需求:

    单一分组:按照状态分组

    多重分组:先按照状态分组,再按照年龄分组(以26为界,大于26为中老年,小于26为青少年)

        Map map3 = students1.stream().collect(Collectors.groupingBy(Student::getStatus));
log.info("收集:collect按照Status分组测试结果{}", JSON.toJSONString(map3)); Map<Status,Map<String,List<Student>>> map = students1.stream().collect(Collectors.groupingBy(Student::getStatus
,Collectors.groupingBy((x)->{
if(((Student)x).getAge() > ){
return "中老年";
}else{
return "青少年";
}
})
));
log.info("收集:collect按照Status分组后按照年龄二次分组测试结果{}", JSON.toJSONString(map));

  测试结果:

-- ::37.591  INFO  --- [           main] com.example.jdk8demo.Jdk8StreamDemoTest  : 收集:collect按照Status分组测试结果{"VOCATION":[{"age":,"name":"lcl2","status":"VOCATION"}],"FREE":[{"age":,"name":"lcl3","status":"FREE"},{"age":,"name":"lcl4","status":"FREE"},{"age":,"name":"lcl6","status":"FREE"},{"age":,"name":"lcl2","status":"FREE"}],"BUSY":[{"age":,"name":"lcl1","status":"BUSY"},{"age":,"name":"lcl5","status":"BUSY"}]}
-- ::37.592 INFO --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : 收集:collect按照Status分组后按照年龄二次分组测试结果{"VOCATION":{"中老年":[{"age":,"name":"lcl2","status":"VOCATION"}]},"FREE":{"中老年":[{"age":,"name":"lcl3","status":"FREE"},{"age":,"name":"lcl2","status":"FREE"}],"青少年":[{"age":,"name":"lcl4","status":"FREE"},{"age":,"name":"lcl6","status":"FREE"}]},"BUSY":{"青少年":[{"age":,"name":"lcl1","status":"BUSY"},{"age":,"name":"lcl5","status":"BUSY"}]}}

  (4)使用IntSummaryStatistics计算总数、总和、最大值、最小值、平均值等操作

        IntSummaryStatistics intSummaryStatistics = students1.stream().collect(Collectors.summarizingInt(Student::getAge));
log.info("收集:collect按照年龄平均值{},总数{},最大值{},最小值{},总和{}", intSummaryStatistics.getAverage(),intSummaryStatistics.getCount(),intSummaryStatistics.getMax(),intSummaryStatistics.getMin(),intSummaryStatistics.getSum());

  测试结果:

-- ::37.595  INFO  --- [           main] com.example.jdk8demo.Jdk8StreamDemoTest  : 收集:collect按照年龄平均值25.,总数7,最大值50,最小值8,总和181

  (5)字符串操作

        String s = students1.stream().map(Student::getName).collect(Collectors.joining("=="));
log.info("收集:collect连接字符串测试结果{}", s);

  测试结果:

-- ::37.595  INFO  --- [           main] com.example.jdk8demo.Jdk8StreamDemoTest  : 收集:collect连接字符串测试结果lcl1==lcl2==lcl3==lcl4==lcl5==lcl6==lcl2

JDK8--06:Stream流的更多相关文章

  1. Jdk8中Stream流的使用,让你脱离for循环

    学习要求: 知道一点儿函数式接口和Lambda表达式的基础知识,有利于更好的学习. 1.先体验一下Stream的好处 需求:给你一个ArrayList用来保存学生的成绩,让你打印出其中大于60的成绩. ...

  2. jdk8的stream流式计算的操作

    jdk8之后增加了流式计算,现在根据学习了流式计算,并把过程记录下来: Person.java的bean package com.zhang.collectordemo; /** * @program ...

  3. JDK8新特性---stream流

    项目上用到了stream流,找篇blog,转载一下,介绍下Stream流的用法. 1 流概述  流是 JDK8 新增的成员,允许以声明性方式处理数据集合,可以把 Stream 流看作是遍历数据集合的一 ...

  4. 【JDK8】Java8 Stream流API常用操作

    Java版本现在已经发布到JDK13了,目前公司还是用的JDK8,还是有必要了解一些JDK8的新特性的,例如优雅判空的Optional类,操作集合的Stream流,函数式编程等等;这里就按操作例举一些 ...

  5. JDK8新特性关于Stream流

    在Java1.8之前还没有stream流式算法的时候,我们要是在一个放有多个User对象的list集合中,将每个User对象的主键ID取出,组合成一个新的集合,首先想到的肯定是遍历,如下: 1 2 3 ...

  6. (六)jdk8学习心得之Stream流

    六.Stream流 1. 什么是stream流 现阶段,可以把stream流看成一个高级版的Iterator.普通的Iterator只能实现遍历,遍历做什么,就需要具体些功能代码函数了.而这个stre ...

  7. JDK8新特性之Stream流

    是什么是Stream流 java.util.stream.Stream Stream流和传统的IO流,它们都叫流,却是两个完全不一样的概念和东西. 流可以简单的说是处理数据集合的东西,可以申明式流式A ...

  8. 【JDK8】JDK 8 中Stream流中的去重的方法

    JDK 8 中Stream流中去重的方法 1.简单的去重,可以使用distinct()方法去重,该方法是通过比较equals和hashcode值去去重, 2.复杂的去重, 例如,在一个JavaBean ...

  9. stream流操作List工具类

    工作中操作List对于程序猿来说是"基本操作",为了更加便利,对JDK8的新特性stream流进行二次封装.话不多说,直接上代码 package com.mydemo; impor ...

  10. 还看不懂同事的代码?超强的 Stream 流操作姿势还不学习一下

    Java 8 新特性系列文章索引. Jdk14都要出了,还不能使用 Optional优雅的处理空指针? Jdk14 都要出了,Jdk8 的时间处理姿势还不了解一下? 还看不懂同事的代码?Lambda ...

随机推荐

  1. docker重启提示已存在一个容器的问题处理

    一.问题:在vmware虚拟机中测试以docker方式安装的prometheus,当重启虚拟机后,再次运行prometheus的执行文件,提示已有名称为prometheus的容器存在. 二.处理过程 ...

  2. 程序员的脑袋系列---利用ffmpeg命令提取音频

    今日各大播放器的版权控制越来越严格.导致很多歌曲无法听,但是MV却可以听.这样很蛋疼有木有? 然而,我们可以利用ffmpeg工具提取MV的音频,比如做成MP3格式,这样就可以听了.--哈哈(邪恶地笑) ...

  3. Java实现 LeetCode 771 宝石与石头(这是真暴力)

    771. 宝石与石头 给定字符串J 代表石头中宝石的类型,和字符串 S代表你拥有的石头. S 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石. J 中的字母不重复,J 和 ...

  4. Java实现 蓝桥杯VIP 算法训练 友好数

    有两个整数,如果每个整数的约数和(除了它本身以外)等于对方,我们就称这对数是友好的.例如: 9的约数和有:1+3=4 4的约数和有:1+2=3 所以9和4不是友好的. 220的约数和有:1 2 4 5 ...

  5. Java实现蓝桥杯互补二元组

    分三处 1.当差值为0并且只有一个二元组就不管他 2.当差值为0并且二元组个数>=1加上他并减去它本身 3.当差值为存在并且不为0时直接加上他 因为都计算了两次,所以最后ans/2 用了map的 ...

  6. java实现第四届蓝桥杯马虎的算式

    马虎的算式 题目描述 小明是个急性子,上小学的时候经常把老师写在黑板上的题目抄错了. 有一次,老师出的题目是:36 x 495 = ? 他却给抄成了:396 x 45 = ? 但结果却很戏剧性,他的答 ...

  7. Linux权限管理命令chown、chgrp、umask详解

    命令chown详解 命令chown,所在路径为: 可以看到,这个命令的路径为:/usr/bin/chown ,所以它的执行权限是所有用户 命令的基本功能是改变文件或目录的所有者(只有root可以进行, ...

  8. 【JVM故事】一个Java字节码文件的诞生记

    万字长文,完全虚构. (一) 组里来了个实习生,李大胖面完之后,觉得水平一般,但还是留了下来,为什么呢?各自猜去吧. 李大胖也在心里开导自己,学生嘛,不能要求太高,只要肯上进,慢慢来.就称呼为小白吧. ...

  9. https://www.cnblogs.com/mrchige/p/6409444.html

    https://www.cnblogs.com/mrchige/p/6409444.html http://c.biancheng.net/view/2172.html https://www.cnb ...

  10. 还在用SimpleDateFormat格式化时间?小心经理锤你

    还在用SimpleDateFormat格式化时间?小心经理锤你 场景 本来开开心心的周末时光,线上突然就疯狂报错,以为程序炸了,截停日志,发现是就是类似下述一段错误 java.lang.NumberF ...