一、概述

Stream 是一组用来处理数组、集合的API,Stream API 提供了一种高效且易于使用的处理数据的方式。

Java 8 中之所以费这么大的功夫引入 函数式编程 ,原因有两个:

  • 代码简洁函数式编程写出的代码简洁且意图明确,使用stream接口让你从此告别for循环。
  • 多核友好,Java函数式编程使得编写并行程序从未如此简单,你需要的全部就是用用一下parallel()方法
  • Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作

二、Stream特性

1、不是数据结构,没有内部存储,不会保存数据,故每个Stream流只能使用一次

2、不支持索引访问

3、支持并行

4、很容易生成数据或集合(List,Set)

5、支持过滤、查找、转换、汇总、聚合等操作

6、延迟计算,流在中间处理过程中,只是对操作进行了记录,并不会立即执行,需要等到执行终止操作的时候才会进行实际的计算

三、分类

关于应用在Stream流上的操作,可以分成两种:

  1. Intermediate(中间操作): 中间操作的返回结果都是Stream,故可以多个中间操作叠加;
  2. Terminal(终止操作): 终止操作用于返回我们最终需要的数据,只能有一个终止操作。

使用Stream流,可以清楚地知道我们要对一个数据集做何种操作,可读性强。而且可以很轻松地获取并行化Stream流,不用自己编写多线程代码,可以让我们更加专注于业务逻辑。



无状态: 指元素的处理不受之前元素的影响;

有状态: 指该操作只有拿到所有元素之后才能继续下去。

非短路操作: 指必须处理所有元素才能得到最终结果;

短路操作: 指遇到某些符合条件的元素就可以得到最终结果,如 A || B,只要A为true,则无需判断B的结果。

四、Stream的创建

1、通过数组来生成

2、通过集合来生成

3、通过Stream.generate方法来创建

4、通过Stream.iterate方法来创建

5、其他Api创建

4.1 通过数组来生成

 //通过数组来生成
static void gen1(){
String[] strs = {"a","b","c","d"};
Stream<String> strs1 = Stream.of(strs);//使用Stream中的静态方法:of()
strs1.forEach(System.out::println);//打印输出(a、b、c、d)
}

4.2 通过集合来生成

//通过集合来生成
static void gen2(){
List<String> list = Arrays.asList("1","2","3","4");
Stream<String> stream = list.stream();//获取一个顺序流
stream.forEach(System.out::println);//打印输出(1,2,3,4)
}

4.3 通过Stream.generate方法来创建

    //generate
static void gen3(){
Stream<Integer> generate = Stream.generate(() -> 1);//使用Stream中的静态方法:generate()
//limit 返回由该流的元素组成的流,截断长度不能超过maxSize
generate.limit(10).forEach(System.out::println);//打印输出(打印10个1)
}

4.4 通过Stream.iterate方法来创建

    //使用iterator
static void gen4() {
Stream<Integer> iterate = Stream.iterate(1, x -> x + 1);//使用Stream中的静态方法:iterate()
iterate.limit(10).forEach(System.out::println);//打印输出(1,2,3,4,5,6,7,8,9,10)
}

4.4 其他Api创建

//其他方式
static void gen5(){
String str = "abcdefg";
IntStream stream =str.chars();//获取str 字节码
stream.forEach(System.out::println);//打印输出(97,98,99,100,101,102,103)
}

五、Stream的常用API

5.1 中间操作

1. filter: 过滤流中的某些元素
 //中间操作:如果调用方法之后返回的结果是Stream对象就意味着是一个中间操作
Arrays.asList(1,2,3,4,5).stream()//获取顺序流
.filter((x)->x%2==0) // 2 4
.forEach(System.out::println); //求出结果集中所有偶数的和
int count = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream()//获取顺序流
.filter(x -> x % 2 == 0).// 2 4 6 8
mapToInt(x->x).sum();//求和
System.out.println(count); //打印输出 20
2. distinct: 通过流中元素的 hashCode() 和 equals() 去除重复元素
 Arrays.asList(1,2,3,3,3,4,5,2).stream()//获取顺序流
.distinct()//去重
.forEach(System.out::println);// 打印输出(1,2,3,4,5) System.out.println("去重:---------------"); Arrays.asList(1,2,3,3,3,4,5,2).stream()//获取顺序流
.collect(Collectors.toSet())//Set()去重
.forEach(System.out::println);// 打印输出(1,2,3,4,5)
3. 排序

sorted():返回由此流的元素组成的流,根据自然顺序排序。

sorted(Comparator com):返回由该流的元素组成的流,根据提供的 Comparator进行排序。

//获取最大值和最小值但是不使用min和max方法
List<Integer> list = Arrays.asList(1,2, 3,4, 5, 6);
Optional<Integer> min = list.stream().sorted().findFirst();//自然排序 根据数字从小到大排列
System.out.println(min.get());//打印输出(1) Optional<Integer> max2 = list.stream().sorted((a, b) -> b - a).findFirst();//定时排序 根据最大数进行排序
System.out.println(max2.get());//打印输出(6) //按照大小(a-z)排序
Arrays.asList("java","c#","python","scala").stream().sorted().forEach(System.out::println);
//按照长度排序
Arrays.asList("java","c#","python","scala").stream().sorted((a,b)->a.length()-b.length()).forEach(System.out::println);
4. 截取

limit(n):返回由此流的元素组成的流,截短长度不能超过 n

skip(n):在丢弃流的第n元素后,配合limit(n)可实现分页

//打印20-30这样的集合数据
Stream.iterate(1,x->x+1).limit(50)// limit 50 总共到50
.skip(20)// 跳过前 20
.limit(10) // 打印10个
.forEach(System.out::println);//打印输出(21,22,23,24,25,26,27,28,29,30)
5. 转换

map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

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

List<String> list = Arrays.asList("a,b,c", "1,2,3");

//将每个元素转成一个新的且不带逗号的元素
Stream<String> s1 = list.stream().map(s -> s.replaceAll(",", ""));
s1.forEach(System.out::println); // abc 123 Stream<String> s3 = list.stream().flatMap(s -> {
//将每个元素转换成一个stream
String[] split = s.split(",");
Stream<String> s2 = Arrays.stream(split);
return s2;
});
s3.forEach(System.out::println); // a b c 1 2 3
6. 消费

peek:如同于map,能得到流中的每一个元素。但map接收的是一个Function表达式,有返回值;而peek接收的是Consumer表达式,没有返回值。

 //将str中的每一个数值都打印出来,同时算出最终的求和结果
String str ="11,22,33,44,55";
System.out.println(Stream.of(str.split(",")).peek(System.out::println).mapToInt(Integer::valueOf).sum());//11 22 33 44 55 165

5.2 终止操作

1. 循环:forEach

Users类:

import java.util.Date;

/**
* @program: lambda
* @ClassName Users
* @description:
* @author: muxiaonong
* @create: 2020-10-24 11:00
* @Version 1.0
**/
public class Users { private String name;
public Users() {} /**
* @param name
*/
public Users(String name) {
this.name = name;
} /**
* @param name
* @return
*/
public static Users build(String name){
Users u = new Users();
u.setName(name);
return u;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return "name='" + name + '\'';
}
}
   //创建一组自定义对象
String str2 = "java,scala,python";
Stream.of(str2.split(",")).map(x->new Users(x)).forEach(System.out::println);//打印输出(name='java' name='scala' name='python')
Stream.of(str2.split(",")).map(Users::new).forEach(System.out::println);//打印输出(name='java' name='scala' name='python')
Stream.of(str2.split(",")).map(x->Users.build(x)).forEach(System.out::println);//打印输出(name='java' name='scala' name='python')
Stream.of(str2.split(",")).map(Users::build).forEach(System.out::println);//打印输出(name='java' name='scala' name='python')
2. 计算:min、max、count、sum

min:返回流中元素最小值

max:返回流中元素最大值

count:返回流中元素的总个数

sum:求和

 //求集合中的最大值
List<Integer> list = Arrays.asList(1,2, 3,4, 5, 6);
Optional<Integer> max = list.stream().max((a, b) -> a - b);
System.out.println(max.get()); // 6
//求集合的最小值
System.out.println(list.stream().min((a, b) -> a-b).get()); // 1
//求集合的总个数
System.out.println(list.stream().count());//6
//求和
String str ="11,22,33,44,55";
System.out.println(Stream.of(str.split(",")).mapToInt(x -> Integer.valueOf(x)).sum());
System.out.println(Stream.of(str.split(",")).mapToInt(Integer::valueOf).sum());
System.out.println(Stream.of(str.split(",")).map(x -> Integer.valueOf(x)).mapToInt(x -> x).sum());
System.out.println(Stream.of(str.split(",")).map(Integer::valueOf).mapToInt(x -> x).sum());
3. 匹配:anyMatch、 allMatch、 noneMatch、 findFirst、 findAny

anyMatch:接收一个 Predicate 函数,只要流中有一个元素满足该断言则返回true,否则返回false

allMatch:接收一个 Predicate 函数,当流中每个元素都符合该断言时才返回true,否则返回false

noneMatch:接收一个 Predicate 函数,当流中每个元素都不符合该断言时才返回true,否则返回false

findFirst:返回流中第一个元素

findAny:返回流中的任意元素

List<Integer> list = Arrays.asList(1,2, 3,4, 5, 6);
System.out.println(list.stream().allMatch(x -> x>=0)); //如果集合中的元素大于等于0 返回true
System.out.println(list.stream().noneMatch(x -> x > 5));//如果集合中的元素有大于5的元素。返回false
System.out.println(list.stream().anyMatch(x -> x > 4));//如果集合中有大于四4的元素,返回true
//取第一个偶数
Optional<Integer> first = list.stream().filter(x -> x % 10 == 6).findFirst();
System.out.println(first.get());// 6
//任意取一个偶数
Optional<Integer> any = list.stream().filter(x -> x % 2 == 0).findAny();
System.out.println(any.get());// 2
4.收集器:toArray、collect

collect:接收一个Collector实例,将流中元素收集成另外一个数据结构

Collector<T, A, R> 是一个接口,有以下5个抽象方法:

  1. Supplier<A> supplier();创建一个结果容器A
  2. BiConsumer<A, T> accumulator();:消费型接口,第一个参数为容器A,第二个参数为流中元素T。
  3. BinaryOperator<A> combiner();函数接口,该参数的作用跟上一个方法(reduce)中的combiner参数一样,将并行流中各个子进程的运行结果(accumulator函数操作后的容器A)进行合并。
  4. Function<A, R> finisher();函数式接口,参数为:容器A,返回类型为:collect方法最终想要的结果R。
  5. Set<Characteristics> characteristics();返回一个不可变的Set集合,用来表明该Collector的特征
/**
* @program: lambda
* @ClassName Customer
* @description:
* @author: muxiaonong
* @create: 2020-10-24 11:36
* @Version 1.0
**/
public class Customer { private String name; private Integer age; ...getset忽略
}
 public static void main(String[] args) {
Customer c1 = new Customer("张三",10);
Customer c2 = new Customer("李四",20);
Customer c3 = new Customer("王五",10); List<Customer> list = Arrays.asList(c1,c2,c3); //转成list
List<Integer> ageList = list.stream().map(Customer::getAge).collect(Collectors.toList());
System.out.println("ageList:"+ageList);//ageList:[10, 20, 10] //转成set
Set<Integer> ageSet = list.stream().map(Customer::getAge).collect(Collectors.toSet());
System.out.println("ageSet:"+ageSet);//ageSet:[20, 10] //转成map,注:key不能相同,否则报错
Map<String, Integer> CustomerMap = list.stream().collect(Collectors.toMap(Customer::getName, Customer::getAge));
System.out.println("CustomerMap:"+CustomerMap);//CustomerMap:{李四=20, 张三=10, 王五=10} //字符串分隔符连接
String joinName = list.stream().map(Customer::getName).collect(Collectors.joining(",", "(", ")"));
System.out.println("joinName:"+joinName);//joinName:(张三,李四,王五) //聚合操作
//1.学生总数
Long count = list.stream().collect(Collectors.counting());
System.out.println("count:"+count);//count:3
//2.最大年龄 (最小的minBy同理)
Integer maxAge = list.stream().map(Customer::getAge).collect(Collectors.maxBy(Integer::compare)).get();
System.out.println("maxAge:"+maxAge);//maxAge:20 //3.所有人的年龄
Integer sumAge = list.stream().collect(Collectors.summingInt(Customer::getAge));
System.out.println("sumAge:"+sumAge);//sumAge:40 //4.平均年龄
Double averageAge = list.stream().collect(Collectors.averagingDouble(Customer::getAge));
System.out.println("averageAge:"+averageAge);//averageAge:13.333333333333334 //分组
Map<Integer, List<Customer>> ageMap = list.stream().collect(Collectors.groupingBy(Customer::getAge));
System.out.println("ageMap:"+ageMap);//ageMap:{20=[com.mashibing.stream.Customer@20ad9418], 10=[com.mashibing.stream.Customer@31cefde0, com.mashibing.stream.Customer@439f5b3d]} //分区
//分成两部分,一部分大于10岁,一部分小于等于10岁
Map<Boolean, List<Customer>> partMap = list.stream().collect(Collectors.partitioningBy(v -> v.getAge() > 10));
System.out.println("partMap:"+partMap); //规约
Integer allAge = list.stream().map(Customer::getAge).collect(Collectors.reducing(Integer::sum)).get();
System.out.println("allAge:"+allAge);//allAge:40 }

六、Stream的方法摘要

修饰符和类型 方法和说明
static Collector<T,?,Double> averagingDouble(ToDoubleFunction<? super T> mapper) 返回一个 Collector ,它产生应用于输入元素的双值函数的算术平均值。
static Collector<T,?,Double> averagingInt(ToIntFunction<? super T> mapper) 返回一个 Collector ,它产生应用于输入元素的整数值函数的算术平均值。
static Collector<T,?,Double> averagingLong(ToLongFunction<? super T> mapper) 返回一个 Collector ,它产生应用于输入元素的长值函数的算术平均值。
static <T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream, Function<R,RR> finisher) 适应 Collector进行额外的整理转换。
static Collector<T,?,Long> counting() 返回 Collector类型的接受元件 T计数输入元件的数量。
static <T,K> Collector<T,?,Map<K,List>> groupingBy(Function<? super T,? extends K> classifier) 返回 Collector “由基团”上的类型的输入元件操作实现 T ,根据分类功能分组元素,并且在返回的结果 Map 。
static <T,K,A,D> Collector<T,?,Map<K,D>> groupingBy(Function<? super T,? extends K> classifier, Collector<? super T,A,D> downstream) 返回 Collector “由基团”上的类型的输入元件操作实现级联 T ,根据分类功能分组元素,然后使用下游的指定执行与给定键相关联的值的归约运算 Collector 。
static <T,K,D,A,M extends Map<K,D>>Collector<T,?,M> groupingBy(Function<? super T,? extends K> classifier, Supplier mapFactory, Collector<? super T,A,D> downstream) 返回 Collector “由基团”上的类型的输入元件操作实现级联 T ,根据分类功能分组元素,然后使用下游的指定执行与给定键相关联的值的归约运算 Collector 。
static <T,K> Collector<T,?,ConcurrentMap<K,List>> groupingByConcurrent(Function<? super T,? extends K> classifier) 返回一个并发 Collector “由基团”上的类型的输入元件操作实现 T ,根据分类功能分组元素。
static <T,K,A,D> Collector<T,?,ConcurrentMap<K,D>> groupingByConcurrent(Function<? super T,? extends K> classifier, Collector<? super T,A,D> downstream) 返回一个并发 Collector “由基团”上的类型的输入元件操作实现级联 T ,根据分类功能分组元素,然后使用下游的指定执行与给定键相关联的值的归约运算 Collector 。
static <T,K,A,D,M extends ConcurrentMap<K,D>> Collector<T,?,M> groupingByConcurrent(Function<? super T,? extends K> classifier, Supplier mapFactory, Collector<? super T,A,D> downstream) 返回一个并发 Collector “由基团”上的类型的输入元件操作实现级联 T ,根据分类功能分组元素,然后使用下游的指定执行与给定键相关联的值的归约运算 Collector 。
static Collector<CharSequence,?,String> joining() 返回一个 Collector ,按照遇到的顺序将输入元素连接到一个 String中。
static Collector<CharSequence,?,String> joining(CharSequence delimiter) 返回一个 Collector ,按照遇到的顺序连接由指定的分隔符分隔的输入元素。
static Collector<CharSequence,?,String> joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix) 返回一个 Collector ,它将按照指定的 Collector分隔的输入元素与指定的前缀和后缀进行连接。
static <T,U,A,R> Collector<T,?,R> mapping(Function<? super T,? extends U> mapper, Collector<? super U,A,R> downstream) 适应一个 Collector类型的接受元件 U至类型的一个接受元件 T通过积累前应用映射函数到每个输入元素。
static Collector<T,?,Optional> maxBy(Comparator<? super T> comparator) 返回一个 Collector ,它根据给出的 Comparator产生最大元素,描述为 Optional 。
static Collector<T,?,Optional> minBy(Comparator<? super T> comparator) 返回一个 Collector ,根据给出的 Comparator产生最小元素,描述为 Optional 。
static Collector<T,?,Map<Boolean,List>> partitioningBy(Predicate<? super T> predicate) 返回一个 Collector ,根据Predicate对输入元素进行 Predicate ,并将它们组织成 Map<Boolean, List> 。
static <T,D,A> Collector<T,?,Map<Boolean,D>> partitioningBy(Predicate<? super T> predicate, Collector<? super T,A,D> downstream) 返回一个 Collector ,它根据Predicate对输入元素进行 Predicate ,根据另一个 Collector减少每个分区的值,并将其组织成 Map<Boolean, D> ,其值是下游缩减的结果。
static Collector<T,?,Optional> reducing(BinaryOperator op) 返回一个 Collector ,它在指定的 Collector下执行其输入元素的 BinaryOperator 。
static Collector<T,?,T> reducing(T identity, BinaryOperator op) 返回 Collector执行下一个指定的减少其输入元件的 BinaryOperator使用所提供的身份。
static <T,U> Collector<T,?,U> reducing(U identity, Function<? super T,? extends U> mapper, BinaryOperator op) 返回一个 Collector ,它在指定的映射函数和 BinaryOperator下执行其输入元素的 BinaryOperator 。
static Collector<T,?,DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper) 返回一个 Collector , double生产映射函数应用于每个输入元素,并返回结果值的汇总统计信息。
static Collector<T,?,IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper) 返回一个 Collector , int生产映射函数应用于每个输入元素,并返回结果值的汇总统计信息。
static Collector<T,?,LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper) 返回一个 Collector , long生产映射函数应用于每个输入元素,并返回结果值的汇总统计信息。
static Collector<T,?,Double> summingDouble(ToDoubleFunction<? super T> mapper) 返回一个 Collector ,它产生应用于输入元素的双值函数的和。
static Collector<T,?,Integer> summingInt(ToIntFunction<? super T> mapper) 返回一个 Collector ,它产生应用于输入元素的整数值函数的和。
static Collector<T,?,Long> summingLong(ToLongFunction<? super T> mapper) 返回一个 Collector ,它产生应用于输入元素的长值函数的和。
static <T,C extends Collection> Collector<T,?,C> toCollection(Supplier collectionFactory) 返回一个 Collector ,按照遇到的顺序将输入元素累加到一个新的 Collection中。
static <T,K,U> Collector<T,?,ConcurrentMap<K,U>> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper) 返回一个并发的 Collector ,它将元素累加到 ConcurrentMap ,其键和值是将所提供的映射函数应用于输入元素的结果。
static <T,K,U> Collector<T,?,ConcurrentMap<K,U>> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator mergeFunction) 返回一个并发的 Collector ,它将元素累加到一个 ConcurrentMap ,其键和值是将提供的映射函数应用于输入元素的结果。
static <T,K,U,M extends ConcurrentMap<K,U>> Collector<T,?,M> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator mergeFunction, Supplier mapSupplier) 返回一个并发的 Collector ,它将元素累加到一个 ConcurrentMap ,其键和值是将所提供的映射函数应用于输入元素的结果。
static Collector<T,?,List> toList() 返回一个 Collector ,它将输入元素 List到一个新的 List 。
static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper) 返回一个 Collector ,它将元素累加到一个 Map ,其键和值是将所提供的映射函数应用于输入元素的结果。
static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator mergeFunction) 返回一个 Collector ,它将元素累加到 Map ,其键和值是将提供的映射函数应用于输入元素的结果。
static <T,K,U,M extends Map<K,U>> Collector<T,?,M> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator mergeFunction, Supplier mapSupplier) 返回一个 Collector ,它将元素累加到一个 Map ,其键和值是将所提供的映射函数应用于输入元素的结果。
static Collector<T,?,Set> toSet() 返回一个 Collector ,将输入元素 Set到一个新的 Set 。

总结

对于Java中新特性除了 Stream 还有lamaba表达式都是可以帮忙我们很好的去优化代码,使我们的代码简洁且意图明确,避免繁琐的重复性的操作,对于文中有兴趣的小伙伴可以操作起来,又不懂的小伙伴可以在下面进行留言,小农看到了会第一时间回复大家,谢谢,大家加油!

JDK新特性——Stream代码简洁之道的详细用法的更多相关文章

  1. JDK1.8新特性——Stream API

    JDK1.8新特性——Stream API 摘要:本文主要学习了JDK1.8的新特性中有关Stream API的使用. 部分内容来自以下博客: https://blog.csdn.net/icarus ...

  2. JDK新特性关于流操作部分

    // array 工具类 可以用来快捷的将数组转化为list List<String> strings = Arrays.asList("zhongguo", &quo ...

  3. Java8 新特性 Stream() API

    新特性里面为什么要加入流Steam() 集合是Java中使用最多的API,几乎每一个Java程序都会制造和处理集合.集合对于很多程序都是必须的,但是如果一个集合进行,分组,排序,筛选,过滤...这些操 ...

  4. Java8 新特性 Stream 非短路终端操作

    非短路终端操作 Java8 新特性 Stream 练习实例 非短路终端操作,就是所有的元素都遍厉完,直到最后才结束.用来收集成自己想要的数据. 方法有: 遍厉 forEach 归约 reduce 最大 ...

  5. Java8 新特性 Stream 短路终端操作

    短路终端操作 Java8 新特性 Stream 练习实例 传入一个谓词,返回传为boolean,如果符合条件,则直接结束流. 匹配所有 allMatch 任意匹配 anymMatch 不匹配 none ...

  6. Java8 新特性 Stream 无状态中间操作

    无状态中间操作 Java8 新特性 Stream 练习实例 中间无状态操作,可以在单个对单个的数据进行处理.比如:filter(过滤)一个元素的时候,也可以判断,比如map(映射)... 过滤 fil ...

  7. java新特性stream

    java新特性stream,也称为流式编程. 在学习stream之前先了解一下java内置的四大函数 第一种函数式函数,后面是lambda表达式写法 /*Function<String,Inte ...

  8. 史上最全jdk新特性总结,涵盖jdk8到jdk15!

    前言 在本文中,我将描述自第8版以来Java最重要且对开发人员友好的功能.为什么会有这样的主意?在Web上,您可以找到许多文章,其中包含每种Java版本的新功能列表.但是,由于缺少文章,因此无法简要概 ...

  9. 这可能是史上最好的 Java8 新特性 Stream 流教程

    本文翻译自 https://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/ 作者: @Winterbe 欢迎关注个人微信公众 ...

随机推荐

  1. PE安装window 10操作系统

    一.进入bios,通过u盘启动 1. 在bios中选择U盘启动 2. 选择第二选项,如果是老机器,就选择03或者04 二.进入PE操作系统后: 打开桌面上的Ghost手动工具,点击OK 依次点击loc ...

  2. Netty之ChannelOption的各种参数之EpollChannelOption.SO_REUSEPORT

    socket选项 SO_REUSEPORT 转 miffa 发布于 2015/03/24 17:21 字数 3383 阅读 6076 收藏 6 点赞 1 评论 0 开发十年,就只剩下这套Java开发体 ...

  3. Module build failed: TypeError: this.getResolve is not a function at Object.loader 使用vue-cli 创建项目 使用sass时报错 -- 等其他sass 报错 ./node_modules/css-loader?{"sourceMap":true}!./node_modules/vue-loader/lib

    已经安装了 sass相关依赖包 npm  install sass-loader --save-devnpm install node-sass --sava-dev 并且在build文件下webpa ...

  4. 面试官写了个双冒号: : 问我这是什么语法?Java中有这玩意?

    一:简洁 方法引用分为三种,方法引用通过一对双冒号:: 来表示,方法引用是一种函数式接口的另一种书写方式 静态方法引用,通过类名::静态方法名, 如 Integer::parseInt 实例方法引用, ...

  5. Jackson精解第4篇-@JacksonInject与@JsonAlias注解

    Jackson是Spring Boot(SpringBoot)默认的JSON数据处理框架,但是其并不依赖于任何的Spring 库.有的小伙伴以为Jackson只能在Spring框架内使用,其实不是的, ...

  6. C# NX二次开发环境搭建

    在网上看到一篇C#二次开发环境搭建的文章:NX二次开发-使用NXOPEN C#手工搭建开发环境配置 ,写得非常好.我按照文章操作,过程中遇到几个问题,把问题分享给大家,希望对各位有帮助. 注意三点: ...

  7. XSS基础笔记 from 《Web安全攻防 渗透测试实战指南》

    XSS漏洞介绍 跨站脚本(Cross Site Scripting, 简称为XSS或跨站脚本或跨站脚本攻击)是一种针对网站应用程序的安全漏洞攻击技术,是代码注入的一种.它允许恶意用户将代码注入网页,其 ...

  8. ORA-00060: Deadlock detected 模拟死锁产生与解决方案

    死锁:死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程 ...

  9. Hibernate4.3基础知识1

    一.Hibernate 开发环境搭建 4.3 1.导包    2.创建hibernate.cfg.xml配置文件   3.创建实体类   4.创建映射文件 实体类名.hbm.xml  配置文件 二.h ...

  10. Linux常用命令代码大全

    arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 – (SMBIOS / DMI ...