赞
踩
尚硅谷JavaSE笔记合集
| 文章名 | 链接 |
|---|---|
| 【JavaSE】异常 | 文章地址 |
| 【JavaSE】常用类:String、LocalDateTime… | 文章地址 |
| 【JavaSE】枚举 | 文章地址 |
| 【JavaSE】注解 | 文章地址 |
| 【JavaSE】集合框架 | 文章地址 | HashMap源码解析 | List相关实现类源码解析 |
| 【JavaSE】泛型 | 文章地址 |
| 【JavaSE】IO流 | 文章地址 | 字符编码详解 |
| 【JavaSE】网络编程,BIO需求演进 | 文章地址 |
| 【JavaSE】反射 | 文章地址 |
| 【JavaSE】jdk8新特性 | 文章地址 |

并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。相比较串行的流,并行的流可以很大程度上提高程序的执行效率。
Java 8 中将并行进行了优化,我们可以很容易的对数据进行并行操作。Stream API 可以声明性地通过parallel() 与sequential() 在并行流与顺序流之间进行切换。
Lambda 是一个匿名函数,我们可以把Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。
总结:作为函数式接口的匿名实现类的实现
//语法格式一:无参,无返回值 Runnable r2 = () -> System.out.println("长安欢迎您"); //语法格式二:一个参数,没有返回值。 Consumer<String> c1 = (String s) -> { System.out.println(s); }; c1.accept("先天人性无善恶,后天人性有善恶。"); //语法格式三:因为可由编译器推断得出(“类型推断”),数据类型可以省略, Consumer<String> c2 = (s) -> { System.out.println(s); }; c2.accept("如果没有邪恶的话我们怎么会知道人世间的那些善良呢?"); //语法格式四:只需要一个参数时,小括号可以省略 Consumer<String> c2 = s -> { System.out.println(s); }; c2.accept("如果没有邪恶的话我们怎么会知道人世间的那些善良呢?"); //语法格式五:需要两个或以上的参数,多条执行语句,并且可以有返回值 Comparator<Integer> com2 = (o1,o2) -> { System.out.println(o1); System.out.println(o2); return o1.compareTo(o2); }; System.out.println(com2.compare(16,8)); //语法格式六:Lambda体只有一条语句时,return与大括号都可以省略 Comparator<Integer> c2 = (o1,o2) -> o1.compareTo(o2); System.out.println(c2.compare(17,24));
/*
* 4.Lambda表达式的本质:作为函数式接口的实例
*/
/**
* 自定义函数式接口
*/
@FunctionalInterface //可以使用 @FunctionalInterface 检查它是否是一个函数式接口
public interface MyInterFace {
void method(); //接口中,只声明了一个抽象方法
}
| 函数式接口 | 参数类型 | 返回类型 | 用途 |
|---|---|---|---|
Consumer 消费型接口 | T | void | 对类型为T的对象应用操作,包含方法:void accept(T t) |
Supplier 供给型接口 | 无 | T | 返回类型为T的对象,包含方法:T get() |
Function<T, R> 函数型接口 | T | R | 对类型为T的对象应用操作,并返回结果。结果是R类型的对象。包含方法:R apply(T t) |
Predicate断定型接口 | T | boolean | 确定类型为T的对象是否满足某约束,并返回boolean 值。包含方法:boolean test(T t) |
BiFunction<T,U,R> | T, U | R | 对类型为T,U参数应用操作,返回R类型的结果。包含方法为:Rapply(T t,U u); |
UnaryOperator(Function子接口) | T | T | 对类型为T的对象进行一元运算,并返回T类型的结果。包含方法为:Tapply(T t); |
BinaryOperator(BiFunction子接口) | T,T | T | 对类型为T的对象进行二元运算,并返回T类型的结果。包含方法为:Tapply(T t1,T t2); |
BiConsumer<T,U> | T,U | void | 对类型为T,U参数应用操作。包含方法为:voidaccept(Tt,Uu) |
BiPredicate<T,U> | T,U | boolean | 包含方法为:booleantest(Tt,Uu) |
ToIntFunction | T | int | 计算int值的函数 |
ToLongFunction | T | long | 计算long值的函数 |
ToDoubleFunction | T | double | 计算double值的函数 |
IntFunction | int | R | 参数为int类型的函数 |
LongFunction | long | R | 参数为long类型的函数 |
DoubleFunction | double | R | 参数为double类型的函数 |
/**
* java内置的4大核心函数式接口
*
* 消费型接口 Consumer<T> void accept(T t) 有参数无返回值
* 供给型接口 Supplier<T> T get() 无参数有返回值
* 函数型接口 Function<T,R> R apply(T t) 有参数有返回值
* 断定型接口 Predicate<T> boolean test(T t) 有参数返回真假
*/
当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!
方法引用可以看做是Lambda表达式深层次的表达。换句话说,方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。
:: 方法名对象::实例方法
@Test public void demo1(){ String str="abc"; /*Consumer<String> consumer=(s)->{ System.out.println(s); };*/ Consumer<String> consumer=System.out::println; Supplier<Integer> supplier=str::length; Function<Integer,String> function=str::substring; Predicate<String> predicate=str::endsWith; consumer.accept("方法引用之实例::实例方法(Consumer)"); consumer.accept("方法引用之实例::实例方法(Supplier):"+supplier.get()); consumer.accept("方法引用之实例::实例方法(Function):"+function.apply(0)); consumer.accept("方法引用之实例::实例方法(Predicate):"+predicate.test("c")); }
类::类方法
@Test
public void demo2(){
List<String> list= Arrays.asList("javase","hello","word");
List<String> list2= Arrays.asList("javase","hello");
Consumer<List<String>> consumer= Collections::sort;
Supplier<Iterator> supplier=Collections::emptyIterator;
Function<List<String>,List<String>> function=Collections::synchronizedList;
BiPredicate<List<String>,List<String>> predicate=Collections::disjoint;
consumer.accept(list);
log.debug("方法引用之类::类方法(Consumer):"+list);
log.debug("方法引用之类::类方法(Supplier):"+supplier.get());
log.debug("方法引用之类::类方法(Function):"+function.apply(list));
log.debug("方法引用之类::类方法(Predicate):"+predicate.test(list,list2));
}
类::实例方法
@Test
public void demo3(){
ArrayList<String> list= new ArrayList<>(Arrays.asList("javase","hello","word"));
BiConsumer<List<String>,Consumer> consumer= List::forEach;
BiFunction<List<String>,Object,Integer> function=List::indexOf;
BiPredicate<List<String>,String> predicate=List::contains;
Integer javase = function.apply(list, "javase");
log.debug("方法引用之类::实例方法(Consumer):");
consumer.accept(list,System.out::println);
log.debug("方法引用之类::实例方法(Function):"+javase);
log.debug("方法引用之类::实例方法(Predicate):"+predicate.test(list,"javase"));
}
和方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一致。
抽象方法的返回值类型即为构造器所属的类的类型
@Test
public void demo4(){
Supplier<List> supplier=ArrayList::new;
Function<Integer,Integer> function=Integer::new;
Predicate<Boolean> predicate=Boolean::new;
System.out.println(supplier.get());
System.out.println(function.apply(1));
System.out.println(predicate.test(true));
}
可以把数组看做是一个特殊的类,则写法与构造器引用一致。
@Test
public void demo5(){
Function<Integer,Integer[]> function=Integer[]::new;
System.out.println(function.apply(2));
}
java.util.stream)把真正的函数式编程风格引入到Java中。这是目前为止对Java类库最好的补充,因为Stream API可以极大提供Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。/** * 1.Stream关注的是对数据的运算,与CPU打交道 * 集合关注的是数据的存储,与内存打交道 * * 2.特点 * ①Stream 自己不会存储元素。 * ②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。 * ③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行 * * 3.Stream 执行流程 * ① Stream的实例化 * ② 一系列的中间操作(过滤、映射、...) * ③ 终止操作 * * 4.说明: * 4.1 一个中间操作链,对数据源的数据进行处理 * 4.2 一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用 */

1、通过 java.util.Collection.stream()/parallelStream() 方法用集合创建流
stream():创建顺序流。
parallel():把顺序流转换成并行流
parallelStream():创建并行流。内部以多线程并行执行的方式对流进行操作,但前提是流中的数据处理没有顺序要求
2、使用java.util.Arrays.stream(T[] array)方法用数组创建流
3、使用Stream的静态方法创建流:
- of(1,2,3,4) //有限流
- iterate(0, (x) -> x + 3).limit(4) //无限流
- generate(Math::random).limit(3) //无限流
public class StreamAPITest { //创建 Stream方式一:通过集合 @Test public void test(){ List<Employee> employees = EmployeeData.getEmployees(); // default Stream<E> stream() : 返回一个顺序流 Stream<Employee> stream = employees.stream(); // default Stream<E> parallelStream() : 返回一个并行流 Stream<Employee> parallelStream = employees.parallelStream(); } //创建 Stream方式二:通过数组 @Test public void test2(){ int[] arr = new int[]{1,2,3,4,5,6}; //调用Arrays类的static <T> Stream<T> stream(T[] array): 返回一个流 IntStream stream = Arrays.stream(arr); Employee e1 = new Employee(1001,"Hom"); Employee e2 = new Employee(1002,"Nut"); Employee[] arr1 = new Employee[]{e1,e2}; Stream<Employee> stream1 = Arrays.stream(arr1); } //创建 Stream方式三:通过Stream的of() @Test public void test3(){ Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6); } //创建 Stream方式四:创建无限流 @Test public void test4(){ // 迭代 // public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) //遍历前10个偶数 Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println); // 生成 // public static<T> Stream<T> generate(Supplier<T> s) Stream.generate(Math::random).limit(10).forEach(System.out::println); } }
中间操作
过滤、筛选与切片
- filter(Predicate p):从流中排除某些元素
- distinct():去重
- limit(long maxSize):取前maxSize个元素
- skip(long n):跳过前n个元素
映射
- map(Function f):接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
- flatMap(Function f):接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。
排序
- sorted():自然排序,流中元素需实现Comparable接口
- sorted(Comparator com):Comparator排序器自定义排序
public static final <T> Stream<T> getStream(ArrayList<T> list){ return list.stream(); } /** * 中间操作 * 终止操作-遍历:forEach */ @Test public void demo4(){ Stream<String> stream = getStream(new ArrayList<String>(Arrays.asList("aaa","bbb","ccc"))); //中间操作:映射->排序->限制->切片->去重->过滤 Stream<String> stringStream = stream .map(item -> item + item) .sorted().limit(3) .skip(0) .distinct() .filter(item -> item instanceof String); //终止操作 stringStream.forEach(System.out::println); }
终止操作:从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、Integer,甚至是void 。 遍历 - forEach(Consumer c):内部迭代 匹配与查找 - allMatch(Predicate p): 全部元素是否都符合条件 - anyMatch(Predicate p):是否包含一个符合条件的元素 - noneMatch(Predicate p):是否没有包含符合条件的元素 - findFirst():匹配第一个 - findAny():匹配任意(适用于并行流) - count():统计流中个数 - max(Comparator c):返回流中最大值 - min(Comparator c):返回流中最小值 归约 - reduce(T iden, BinaryOperator b):归约/聚合,返回T。 - reduce(BinaryOperator b):归约/聚合,返回Optional。 收集: collect(Collectors.toList())把一个流收集起来,最终可以是收集成一个值也可以收集成一个新的集合。 - toList() - toSet() - toMap(Person::getName, p -> p) - 计数:counting - 平均值:averagingInt、averagingLong、averagingDouble - 最值:maxBy、minBy - 求和:summingInt、summingLong、summingDouble - 统计以上所有:summarizingInt、summarizingLong、summarizingDouble - partitioningBy:分区。按条件分为两个Map - groupingBy:分组。按参数值分为多个Map - joining(","):将stream中元素用特定的连接符(没有的话,则直接连接)连接成一个字符串 - reducing:相比于stream本身的reduce方法,增加了对自定义归约的支持。
/** * 终止操作:从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、Integer,甚至是void 。 * 匹配与查找 */ @Test public void demo5(){ Stream<String> stream = getStream(new ArrayList<String>(Arrays.asList("aaa", "bbb", "ccc"))); //匹配与查找 // boolean b = stream.allMatch(item -> item instanceof String); // log.debug("匹配与查找allMatch:"+b);//true // boolean aaa = stream.anyMatch(item -> item.equals("aaa")); // log.debug("匹配与查找anyMatch:"+aaa);//true // boolean ddd = stream.noneMatch(item -> item.equals("ddd")); // log.debug("匹配与查找noneMatch:"+ddd);//true // Optional<String> any = stream.parallel().findAny(); // String s = any.get(); // log.debug("匹配与查找findAny:"+s);//bbb // long count = stream.count(); // log.debug("匹配与查找count:"+count);//3 // Optional<String> max = stream.max((a, b) -> a.compareTo(b)); // String s = max.get(); // log.debug("匹配与查找max:"+s);//ccc Optional<String> min = stream.min((a, b) -> a.compareTo(b)); String s = min.get(); log.debug("匹配与查找min:"+s);//aaa } /** * 终止操作:从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、Integer,甚至是void 。 * 归约 */ @Test public void demo6(){ Stream<String> stream = getStream(new ArrayList<String>(Arrays.asList("aaa", "bbb", "ccc"))); // String hello_ = stream.reduce("hello ", (a, b) -> a + b); // log.debug("归约reduce:"+hello_);//hello aaabbbccc Optional<String> reduce = stream.reduce((a, b) -> a + b); String s = reduce.get(); log.debug("归约reduce:"+s);//aaabbbccc } /** * 终止操作:从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、Integer,甚至是void 。 * 收集 */ @Test public void demo7(){ Stream<String> stream = getStream(new ArrayList<String>(Arrays.asList("aaa", "bbb", "ccc"))); // List<String> collect = stream.collect(Collectors.toList()); // log.debug("收集Collectors.toList:"+collect.toString());//[aaa, bbb, ccc] // Set<String> collect1 = stream.collect(Collectors.toSet()); // log.debug("收集Collectors.toSet:"+collect1.toString());//[aaa, ccc, bbb] // Map<String, String> collect = stream.collect(Collectors.toMap(item -> item, item -> item)); // log.debug("收集Collectors.toMap:"+collect.toString());//{aaa=aaa, ccc=ccc, bbb=bbb} // Long collect = stream.collect(Collectors.counting()); // log.debug("收集Collectors.counting:"+collect);//3 // Optional<String> collect = stream.collect(Collectors.maxBy((a, b) -> a.compareTo(b))); // String s = collect.get(); // log.debug("收集Collectors.maxBy:"+s);//ccc // Optional<String> collect = stream.collect(Collectors.minBy((a, b) -> a.compareTo(b))); // String s = collect.get(); // log.debug("收集Collectors.minBy:"+s);//aaa // Map<Boolean, List<String>> aaa = stream.collect(Collectors.partitioningBy(item -> item.equals("aaa"))); // log.debug("收集Collectors.partitioningBy:"+aaa.toString());//{false=[bbb, ccc], true=[aaa]} // Map<String, List<String>> collect = stream.collect(Collectors.groupingBy(item -> item)); // log.debug("收集Collectors.groupingBy:"+collect.toString());//{aaa=[aaa], ccc=[ccc], bbb=[bbb]} // String collect1 = stream.collect(Collectors.joining(" ")); // log.debug("收集Collectors.joining:"+collect1);//aaa bbb ccc Optional<String> collect = stream.collect(Collectors.reducing((a, b) -> a + b)); String s = collect.get(); log.debug("收集Collectors.reducing:"+s);//aaabbbccc }
到目前为止,臭名昭著的空指针异常是导致Java应用程序失败的最常见原因。以前,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。受到Google Guava的启发,Optional类已经成为Java 8类库的一部分。
Optional 类(java.util.Optional) 是一个容器类,它可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在。原来用null 表示一个值不存在,现在Optional 可以更好的表达这个概念。并且可以避免空指针异常。isPresent()方法会返回true,调用get()方法会返回该对象。Optional.of(T t) : 创建一个Optional 实例,t必须非空;通常与get()配合使用Optional.empty() : 创建一个空的Optional 实例Optional.ofNullable(T t):t可以为null。通常与orElse()配合使用boolean isPresent() : 判断是否包含对象void ifPresent(Consumer<? super T> consumer) :如果有值,就执行Consumer接口的实现代码,并且该值会作为参数传给它。T get(): 如果调用对象包含值,返回该值,否则抛异常。通常与of()配合使用T orElse(T other) :如果有值则将其返回,否则返回指定的other对象。通常与ofNullable()配合使用T orElseGet(Supplier<? extends T> other) :如果有值则将其返回,否则返回由Supplier接口实现提供的对象。T orElseThrow(Supplier<? extends X> exceptionSupplier) :如果有值则将其返回,否则抛出由Supplier接口实现提供的异常。1、Boy类
public class Boy { private Girl girl; public Boy() { } public Boy(Girl girl) { this.girl = girl; } public Girl getGirl() { return girl; } public void setGirl(Girl girl) { this.girl = girl; } @Override public String toString() { return "Boy{" + "girl=" + girl + '}'; } }
2、Girl类
public class Girl { private String name; public Girl() { } public Girl(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Girl{" + "name='" + name + '\'' + '}'; } }
3、测试类
import org.junit.Test; import java.util.Optional; /** * Optional类:为了在程序中避免出现空指针异常而创建的。 * * 常用的方法:ofNullable(T t) * orElse(T t) */ public class OptionalTest { /** * Optional.of(T t) : 创建一个 Optional 实例,t必须非空; * Optional.empty() : 创建一个空的 Optional 实例 * Optional.ofNullable(T t):t可以为null */ @Test public void test(){ Girl girl = new Girl(); // girl = null; //of(T t):保证t是非空的 Optional<Girl> optionalGirl = Optional.of(girl); } @Test public void test2(){ Girl girl = new Girl(); // girl = null; //ofNullable(T t):t可以为null Optional<Girl> optionalGirl = Optional.ofNullable(girl); System.out.println(optionalGirl); //orElse(T t1):如果单前的Optional内部封装的t是非空的,则返回内部的t. //如果内部的t是空的,则返回orElse()方法中的参数t1. Girl girl1 = optionalGirl.orElse(new Girl("")); System.out.println(girl1); } }
1、测试类
import org.junit.Test; import java.util.Optional; /** * Optional类:为了在程序中避免出现空指针异常而创建的。 * * 常用的方法:ofNullable(T t) * orElse(T t) */ public class OptionalTest { @Test public void test3(){ Boy boy = new Boy(); boy = null; String girlName = getGirlName(boy); System.out.println(girlName); } private String getGirlName(Boy boy) { return boy.getGirl().getName(); } //优化以后的getGirlName(): public String getGirlName1(Boy boy){ if(boy != null){ Girl girl = boy.getGirl(); if(girl != null){ return girl.getName(); } } return null; } @Test public void test4(){ Boy boy = new Boy(); boy = null; String girlName = getGirlName1(boy); System.out.println(girlName); } //使用Optional类的getGirlName(): public String getGirlName2(Boy boy){ Optional<Boy> boyOptional = Optional.ofNullable(boy); //此时的boy1一定非空 Boy boy1 = boyOptional.orElse(new Boy(new Girl("朱淑贞"))); Girl girl = boy1.getGirl(); Optional<Girl> girlOptional = Optional.ofNullable(girl); //girl1一定非空 Girl girl1 = girlOptional.orElse(new Girl("阿青")); return girl1.getName(); } @Test public void test5(){ Boy boy = null; boy = new Boy(); boy = new Boy(new Girl("李清照")); String girlName = getGirlName2(boy); System.out.println(girlName); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。