那些相见恨晚的Java工具类
Java工具类简介
- 定义: 工具类是对String,Collection,IO等基础、常用功能的封装、扩展
- 目的: 为开发者提供便利,减少重复代码
- 优势: 更快、更好、更容易
CompletableFuture
- 包: java.util.concurrent
- 作用: 构建异步应用,实现异步调用
- 优势: 简化异步编程的复杂性,提供了函数式编程的能力
CompletableFuture的使用
- 构造CompletableFuture对象
-
runAsync方法,不支持返回值
-
supplyAsync方法,支持返回值
-
返回计算结果
-
get方法,抛出具体的异常
-
join抛出具体的异常
例子如下:
CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> { for (int i = 0; i < 5000; i ++) { System.out.println("future1: " + i); } }); CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> { for (int i = 0; i < 5000; i ++) { System.out.println("future2: " + i); } }); CompletableFuture<Void> future3 = CompletableFuture.runAsync(() -> { for (int i = 0; i < 5000; i ++) { System.out.println("future3: " + i); } }); try { future1.get(); future2.get(); future3.get(); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); }
输出如下:
-
-
上一阶段的处理完成后的下一阶段处理
-
thenApply方法,接收上一阶段的处理结果,处理后返回
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "hello") .thenApply(str -> str + " world!"); try { System.out.println(future.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); }
输出:
-
hello world!
-
thenAccept方法,接收上一阶段的处理结果,处理后无返回
CompletableFuture.supplyAsync(() -> "hello").thenAccept(System.out::println);
输出:
hello
-
thenRun方法,不接收上一阶段处理结果,只进行后续操作
CompletableFuture.supplyAsync(() -> "hello").thenRun(() -> System.out.println("then run"));
输出:
then run
-
计算完成后的结果处理或抛出异常的处理
-
whenComplete方法
CompletableFuture.supplyAsync(() -> "hello") .whenComplete((s, throwable) -> System.out.println(s));
输出: hello
-
Stream
-
包:java.util.stream
-
作用:集合数据处理
stream() − 为集合创建串行流。
parallelStream() − 为集合创建并行流。
-
优势: 写出高效率、干净、简洁的代码
遍历一个数组统计1的数目的两种方式对比如下:
// 构造数组 List<Integer> numbers = Stream.of(1,2,3,5,1,2,1,1,5).collect(Collectors.toList()); // 遍历 int count = 0; for (Integer num : numbers) { if (num == 1) { count ++; } } System.out.println(count); // stream long count1 = numbers.stream().filter(num -> num == 1).count(); System.out.println(count1);
Stream的特点
- stream不会存储元素,遍历完一次就等于消费完了;
- stream只会操作数据,不会改变数据;
- stream采用的是内部迭代,访问者模式(Visitor)实现;
- stream中间操作都会返回流对象本身,多个操作串联成一个管道,流式风格,都是懒加载的,只有用到结果的时候才会去执行
Stream的操作
Stream和集合的相互转化
-
stream -> 集合 (.collect)
-
集合 -> stream (.stream或.parallelStream)
// 生成stream Stream<Integer> stream = Stream.of(1,2,3,5,1,2,1,1,5); // stream -> 集合 List<Integer> numbers = stream.collect(Collectors.toList()); // 集合 -> stream Stream<Integer> streamFromList = numbers.stream(); Stream<Integer> parallelStreamFromList = numbers.parallelStream();
中间的操作(对流的操作)
-
filter(Predicate p),在流中筛选一些符合要求的元素
-
distinct(),在流中利用hashCode和equals方法去除相同的元素
-
limit(long maxSize),在流中数据达到最大值时截断流
List<Integer> numbers = Stream.of(1,2,3,5,1,2,1,1,5).collect(Collectors.toList()); numbers = numbers.stream().filter(num -> num <= 4) .distinct().limit(3).collect(Collectors.toList()); System.out.println(numbers);
输出:
[1, 2, 3]
-
skip(long n),丢弃掉流中的前n个元素
-
map(Function function),接受一个函数入参,用在每个元素上,并将其结果映射成一个新的元素
-
flatMap(Function function),接受一个函数入参,该函数会用在每个元素上,并将流中每个元素换到另一个流中.然后将所有的流连在一起.
-
sorted()方法,按照自然规则排序
-
sorted(Comparator comparator)方法,按照给定的规则排序
List<Integer> numbers = Stream.of(1,2,3,5,1,2,1,1,5).collect(Collectors.toList()); // skip List<Integer> numbersSkipped = numbers.stream().skip(3).collect(Collectors.toList()); // 打印出的结果为: [5, 1, 2, 1, 1, 5] System.out.println(numbersSkipped); // map List<Integer> numbersMapped = numbers.stream().map(i -> i + 1).collect(Collectors.toList()); // 打印出的结果为: [2, 3, 4, 6, 2, 3, 2, 2, 6] System.out.println(numbersMapped); // flatMap List<String> strings = Stream.of("A-A-A", "B-B-B").collect(Collectors.toList()); List<String> stringsFlatMapped = strings.stream() .flatMap(i -> Arrays.stream(i.split("-"))).collect(Collectors.toList()); // 打印出的结果为: [A, A, A, B, B, B] System.out.println(stringsFlatMapped); // sorted List<Integer> numbersSorted = numbers.stream().sorted().collect(Collectors.toList()); // 打印出的结果为: [1, 1, 1, 1, 2, 2, 3, 5, 5] System.out.println(numbersSorted); // sorted(Comparator comparator) numbersSorted = numbers.stream() .sorted(Comparator.comparing(Integer::intValue).reversed()).collect(Collectors.toList()); // 打印出的结果为: [5, 5, 3, 2, 2, 1, 1, 1, 1] System.out.println(numbersSorted);
终止操作(操作后获得结果)
-
count(),返回该流存在的元素个数
-
findFirst(),返回该流中第一个元素,返回值为Optional类型
-
findAny(),返回流中任意一个元素,返回值为Optional类型
-
allMatch(Predicate predicate),返回流中所有的元素是否满足Predicate条件
-
anyMatch(Predicate predicate),是否有
-
noneMatch(Predicate predicate),是否都不满足
-
max(Comparator comparator),返回流中Comparator比较后的最大值
-
min(Comparator comparator),返回流中Comparator比较后的最小值
-
forEach(Consumer consumer),对流中所有的元素进行迭代操作(内部迭代),并行执行
-
forEachOrdered(Consumer consumer),对流中所有的元素进行迭代操作(内部迭代),顺序执行
List<Integer> numbers = Stream.of(1,2,3,5,1,2,1,1,5).collect(Collectors.toList()); // 打印出的结果为: 9 System.out.println(numbers.stream().count()); Optional<Integer> firstTwo = numbers.stream().filter(i -> i == 2).findFirst(); // 打印出的结果为: 2 firstTwo.ifPresent(System.out::println); Optional<Integer> anyOne = numbers.stream().filter(i -> i == 1).findAny(); // 打印出的结果为: 1 anyOne.ifPresent(System.out::println); // 打印出的结果为: false System.out.println(numbers.stream().allMatch(i -> i > 4)); // 打印出的结果为: true System.out.println(numbers.stream().anyMatch(i -> i > 4)); // 打印出的结果为: false System.out.println(numbers.stream().noneMatch(i -> i > 4)); Optional<Integer> max = numbers.stream().max(Comparator.naturalOrder()); // 打印出的结果为: 5 max.ifPresent(System.out::println); Optional<Integer> min = numbers.stream().min(Comparator.naturalOrder()); // 打印出的结果为: 1 min.ifPresent(System.out::println); // 打印出的结果为: 123512115 numbers.forEach(System.out::print); // 打印出的结果为: 234623226 numbers.stream().forEachOrdered(i -> System.out.print(i + 1));
归约将集合中的所有元素经过指定运算(加减乘除等),折叠成一个元素输出)
-
reduce(T identity, BinaryOperator accumulator),返回一个T类型的值.第一个值为初始值.
-
reduce(BinaryOperator accumulator),返回一个Optional类型的值.
List<Integer> numbers = Stream.of(1,2,3,5,1,2,1,1,5).collect(Collectors.toList()); Integer multi = numbers.stream().reduce(2, (i1, i2) -> i1 * i2); // 打印出的结果为: 600 System.out.println(multi); Optional<Integer> multi1 = numbers.stream().reduce((i1, i2) -> i1 * i2); // 打印出的结果为: 300 multi1.ifPresent(System.out::println);
Optional
-
包:java.util.Optional
-
作用:是个可以为null的容器对象。它可以保存类型T的值,或者仅仅保存null
-
优势:很好的解决空指针异常
类声明
以下是一个java.util.Optional<T>类的声明:
public final class Optional<T> extends Object
Optional操作
-
empty(),构造一个空Optional实例
-
get(),如果在Optional中包含这个值,返回值,否则抛出NoSuchElementException异常
-
ofPresent(Consumer consumer),如果值存在则使用该值调用consumer , 否则不做任何事情
-
ofNullable(T value),如果为非空,返回Optional描述的指定值
-
orElse(T other),如果存在该值,返回值,否则返回other
public class OptionalTest { public static void main(String[] args) { OptionalTest optionalTest = new OptionalTest(); Integer value1 = null; Integer value2 = 10; // Optional.ofNullable - 允许传递为 null 参数 Optional<Integer> a = Optional.ofNullable(value1); // Optional.of - 如果传递的参数是 null,抛出异常 NullPointerException Optional<Integer> b = Optional.of(value2); System.out.println(optionalTest.sum(a,b)); } public Integer sum(Optional<Integer> a, Optional<Integer> b) { // Optional.isPresent - 判断值是否存在 System.out.println("第一个参数值存在: " + a.isPresent()); System.out.println("第二个参数值存在: " + b.isPresent()); // Optional.orElse - 如果值存在,返回它,否则返回默认值 Integer value1 = a.orElse(0); //Optional.get - 获取值,值需要存在 Integer value2 = b.get(); return value1 + value2; } }