赞
踩
说明:
()-> System.outprintln("hello word!");
Consumer<string> con =(x)->System.out.println(x);
当只有一个参数时可以省略括号
Consumer<string> con =x->System.out.println(x);
BinaryOperator<Integer> bo = (a,b) -> {
system.outprintln("函数式接口);
return a + b;
};
如果编译器无法从lambda匹配的函数式接口抽象方法推断参数类型,则有时可能需要为lambda表达式指定参数类型
(Car car)-> System.out.println("The car is"+ car.getName ());
当Lambda体只有一条语句时,return和大括号可以省略,示例:
BinaryOperator<Integer>bo= (a,b) -> a + b;
//JDK 8之前
new Thread(new Runnable () {
@Override
public void run() {
system.out.printIn("使用匿名内部类,开线程");
}
}).start();
//JDK 8 使用Lambda表达式
new Thread(() -> System.out.println("使用lambda表达式,开线程")).start();
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target (ElementType.TYPE)
public @interface FunctionalInterface {}
Consumer 表示接受一个输入参数并且不返回结果的操作。其中 T 表示输入参数类型。它有一个名为 accept 的抽象方法,可以使用 Lambda 表达式来实现该方法。例如:
Consumer<String> printString = s -> System.out.println(s);
printString.accept("Hello World");
Function<T, R> 表示接受一个输入参数并返回结果的操作。其中 T 表示输入参数类型,R 表示返回结果类型。它有一个名为 apply 的抽象方法,可以使用 Lambda 表达式来实现该方法。例如:
Function<Integer, String> convertToString = i -> i.toString();
String str = convertToString.apply(123);
System.out.println(str);
BiFunction<T, U, R> 表示接受两个输入参数并返回结果的操作。其中 T 和 U 分别表示两个输入参数的类型,R 表示返回结果类型。它有一个名为 apply 的抽象方法,可以使用 Lambda 表达式来实现该方法。例如:
BiFunction<Integer, Integer, Integer> add = (a, b) -> a + b;
int result = add.apply(1, 2);
System.out.println(result);
Supplier 表示提供一个结果的操作。其中 T 表示返回结果的类型。它有一个名为 get 的抽象方法,可以使用 Lambda 表达式来实现该方法。例如:
Supplier<String> getMessage = () -> "Hello World";
String msg = getMessage.get();
System.out.println(msg);
java中的方法引用(Method Reference)是一种简化Lambda表达式的语法,它可以直接引用已有方法或构造方法,并将其作为Lambda表达式的参数传递。方法引用可以使代码更加简洁易读,提高代码的可维护性。需要注意的是,方法引用只是Lambda表达式的一种语法糖,它并不是新的语言特性。
在Java 8中,方法引用的语法格式为:
方法引用类型::方法名
其中,方法引用类型可以是以下四种:
//使用 Integer.parseInt 静态方法引用来将字符串转换为整型
List<String> strList = Arrays.asList("1", "2", "3");
List<Integer> intList = strList.stream()
.map(Integer::parseInt)
.collect(Collectors.toList());
class MyClass { public static void main(String[] args) { // 使用方法引用 //字符串拼接 MyClass obj = new MyClass(); Consumer<String> instanceMethod = obj::instanceMethod; instanceMethod.accept("sssss"); //生成随机数 Random random = new Random(); Function<Integer, Integer> integerFunction = random::nextInt; Integer randomInt = integerFunction.apply(10); } // 实例方法 public void instanceMethod(String name) { System.out.println("Hello " + name); } }
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
class MyPerson{
public static void main(String[] args) {
BiFunction<String, Integer, Person> stringPersonFunction = Person::new;
Person xiaolin = stringPersonFunction.apply("xiaolin", 18);
}
}
使用场景:在需要大量创建数组来存储数据的情况下,示例:
String[] array = Stream.generate(() -> "Hello")
.limit(5)
.toArray(String[]::new);
//---输出---
[Hello, Hello, Hello, Hello, Hello]
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据,Stream流是对集合(Collection)对象功能的增强,与Lambda表达式结合,可以提高编程效率、间接性和程序可读性
两种运行方式:
两种操作方式:
List<String> list = Arrays.asList("apple", "banana", "orange");
Stream<String> stream = list.stream(); // 串行流
Stream<String> parallelStream = list.parallelStream(); // 并行流
int[] arr = {1, 2, 3, 4, 5};
IntStream intStream = Arrays.stream(arr);
注:通过Arrays.stream方法生成流,该方法生成的流是数值流【即IntStream】而不是 Stream,使用数值流可以避免计算过程中拆箱装箱,提高性能。
Stream<String> stream = Stream.of("apple", "banana", "orange");
Stream<Integer> stream = Stream.generate(() -> new Random().nextInt(10)).limit(5);;
Stream<Integer> iterateStream = Stream.iterate(0, n -> n + 2).limit(5);;
注: generate() 或 iterate() 创建的流都是无限流,所以需要用limit(n)进行截断
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
Stream<String> lines = br.lines();
} catch (IOException e) {
e.printStackTrace();
}
注:返回的 Stream
对象,每个字符串表示文件中的一行文本。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
List<String> words = Arrays.asList("apple", "banana", "orange");
List<String> upperCaseWords = words.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
List<Integer> numbers = Arrays.asList(1, 2, 3, 2, 1, 4, 5, 3);
List<Integer> distinctNumbers = numbers.stream()
.distinct()
.collect(Collectors.toList());
List<Integer> numbers = Arrays.asList(3, 1, 4, 2, 5);
List<Integer> sortedNumbers = numbers.stream()
.sorted()
.collect(Collectors.toList());
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> limitedNumbers = numbers.stream()
.limit(3)
.collect(Collectors.toList());
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> skippedNumbers = numbers.stream()
.skip(2)
.collect(Collectors.toList());
List<String> lines = Arrays.asList("hello world", "welcome to java", "stream example");
List<String> words = lines.stream()
.flatMap(line -> Arrays.stream(line.split(" ")))
.collect(Collectors.toList());
System.out.println(words);
//----------输出内容----
[hello, world, welcome, to, java, stream, example]
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> squares = numbers.stream()
.peek(System.out::println)
.map(x -> x * x)
.collect(Collectors.toList());
注:map和peek的区别:
一个流有且只能有一个终端操作,当这个操作执行后,流就被关闭了,无法再被操作,因此一个流只能被遍历一次,若想在遍历需要通过源数据在生成流
forEach:对流中的每个元素进行操作,不返回值。例如:
List<String> list = Arrays.asList("a", "b", "c");
list.stream().forEach(System.out::println);
count:返回流中元素的个数。例如:
List<String> list = Arrays.asList("a", "b", "c");
long count = list.stream().count();
System.out.println(count);
collect:将流中的元素收集到一个集合中。例如:
List<String> list = Arrays.asList("a", "b", "c");
List<String> newList = list.stream().collect(Collectors.toList());
System.out.println(newList);
reduce:对流中的元素进行归约操作。例如:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream().reduce(0, (a, b) -> a + b);
System.out.println(sum);
//上述代码中,reduce()方法将流中的元素归约成一个值,初始值为0,BinaryOperator函数的实现是将两个元素相加
//---输出---
15
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> max = numbers.stream().reduce(Integer::max);
System.out.println(max.get());
//上述代码中,使用Integer::max方法引用作为BinaryOperator函数,将流中的元素归约成一个最大值,最终得到Optional对象,需要使用get()方法获取结果。
//---输出---
5
anyMatch:判断流中是否有任意一个元素满足指定的条件。例如:
List<String> list = Arrays.asList("apple", "banana", "cherry");
boolean result = list.stream().anyMatch(s -> s.startsWith("a"));
System.out.println(result);
//---输出---
true
allMatch:判断流中是否所有元素都满足指定的条件。例如:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
boolean result = list.stream().allMatch(i -> i > 0);
System.out.println(result);
//---输出---
true
noneMatch:判断流中是否没有任何一个元素满足指定的条件。例如:
List<String> list = Arrays.asList("apple", "banana", "cherry");
boolean result = list.stream().noneMatch(s -> s.startsWith("d"));
System.out.println(result);
//---输出---
true
findFirst:返回流中的第一个元素。例如:
List<String> list = Arrays.asList("apple", "banana", "cherry");
Optional<String> first = list.stream().findFirst();
System.out.println(first.get());
//---输出---
apple
findAny:返回流中的任意一个元素。例如:
List<String> list = Arrays.asList("apple", "banana", "cherry");
Optional<String> any = list.stream().findAny();
System.out.println(any.get());
//---输出---
apple
min()、max():返回流中的最小值和最大值,可以接受一个Comparator作为参数进行比较。例如:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> min = list.stream().min(Comparator.naturalOrder());
Optional<Integer> max = list.stream().max(Comparator.naturalOrder());
System.out.println("Min value: " + min.get()); // 输出:Min value: 1
System.out.println("Max value: " + max.get()); // 输出:Max value: 5
sum()方法返回流中所有元素的和。例如:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
int sum = list.stream().mapToInt(Integer::intValue).sum();
System.out.println("Sum: " + sum); // 输出:Sum: 15
Collect收集
Collector:结果收集策略的核心接口,具备将指定元素累加存放到结果容器中的能力;并在Collectors工具中提供了Collector接口的实现
toList(): 将Stream中的元素收集到List中,例如:
List<String> list = Stream.of("apple", "banana", "orange")
.filter(s -> s.contains("a"))
.collect(Collectors.toList());
toSet(): 将Stream中的元素收集到Set中,例如:
Set<Integer> set = Stream.of(1, 2, 3, 2, 1)
.collect(Collectors.toSet());
joining(): 将Stream中的元素连接成一个字符串,例如:
String str = Stream.of("Hello", "World", "Java")
.collect(Collectors.joining(", ", "[", "]"));
//---输出---
[Hello, World, Java]
groupingBy(): 将Stream中的元素按照某个属性分组,例如:
Map<String, List<Person>> personGroups = Stream.of(
new Person("John", "Doe", 28),
new Person("Jane", "Doe", 26),
new Person("Mary", "Smith", 30),
new Person("Tom", "Smith", 32))
.collect(Collectors.groupingBy(Person::getLastName));
partitioningBy(): 将Stream中的元素按照某个条件分成两组,例如:
Map<Boolean, List<Integer>> partitioned = Stream.of(1, 2, 3, 4, 5, 6)
.collect(Collectors.partitioningBy(i -> i % 2 == 0));
//---输出---
{false=[1, 3, 5], true=[2, 4, 6]}
maxBy()/minBy(): 返回Stream中最大/最小的元素,例如:
Optional<Integer> max = Stream.of(1, 2, 3, 4, 5)
.collect(Collectors.maxBy(Integer::compareTo));
Optional<Integer> min = Stream.of(1, 2, 3, 4, 5)
.collect(Collectors.minBy(Integer::compareTo));
counting(): 统计Stream中的元素个数,例如:
long count = Stream.of(1, 2, 3, 4, 5)
.collect(Collectors.counting());
toMap():将流中的元素转化为一个 Map,其中流中的每个元素都将作为 key-value 对的一部分插入到 Map 中,例如:
List<String> words = Arrays.asList("hello", "world", "hello", "java");
Map<String, Integer> wordCountMap = words.stream()
.collect(Collectors.toMap(Function.identity(), s -> 1, Integer::sum));
System.out.println(wordCountMap);
//---输出---
{world=1, java=1, hello=2}
解析:上面的示例中,我们使用了 toMap() 方法,将 words 中的元素转化为一个 Map,其中 key 是元素本身,value 是该元素在流中出现的次数。
summingInt()、summingLong()、summingDouble():将元素转换为整数(Long、Double)后进行求和操作。具体来说,该方法返回一个 Collector 对象,可用于将 Stream 中的元素转换为整数(Long、Double)并求和,示例:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.collect(Collectors.summingInt(Integer::intValue));
System.out.println(sum); // 输出 15
CompletableFuture是Java 8中新增的一个类,用于支持异步编程。它可以在一个任务执行完成后自动触发下一个任务的执行,从而实现
链式调用。同时,CompletableFuture还提供了丰富的方法来处理任务的结果、异常和取消操作,以及等待任务执行完成的方法。
CompletableFuture和Future都是Java中用于异步执行任务的类,但是它们之间有一些重要的区别:
CompletableFuture需要获取返回值,才能获取到异常信息。如果不加 get()/join()方法,看不到异常信息。
CompletableFuture的get()方法是阻塞的。如果使用它来获取异步调用的返回值,需要添加超时时间:
//反例
CompletableFuture.get();
//正例
CompletableFuture.get(5, TimeUnit.SECONDS);
默认线程池的注意点:CompletableFuture代码中使用了默认的线程池,处理的线程个数是电脑CPU核数-1。在大量请求过来的时候,处理逻辑复杂的话,响应会很慢。一般建议使用自定义线程池,优化线程池配置参数。
public static void main(String[] args) throws Exception { long startTime = System.currentTimeMillis(); System.out.println("主线程:程序开始执行"); // 创建一个CompletableFuture对象,表示一个异步任务,任务创建后就会开始执行 CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { try { // 模拟一个长时间运行的任务 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } // 返回任务结果 System.out.println("第一个任务执行完毕"); return "Hello, world!"; }); System.out.println("主线程:我在两个异步任务中间"); //用上一个异步任务的入参作为返回值执行另一个任务,这个任务会等待上一个任务执行完毕后才会执行 CompletableFuture<String> async = future.thenApplyAsync(result -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("第二个异步任务完成"); return result.toUpperCase(); }); System.out.println("主线程:进入睡眠模式,已睡着"); Thread.sleep(3000); //在回调之前 System.out.println("主线程:我睡了3秒,我醒了"); // 等待异步任务完成 System.out.println("主线程:第一个任务返回"+future.get()); //异步回调 System.out.println("主线程:第二个任务返回"+async.get()); long endTime = System.currentTimeMillis(); System.out.println("主线程:程序执行耗时:"+(endTime-startTime)); } //---输出--- 主线程:程序开始执行 主线程:我在两个异步任务中间 主线程:进入睡眠模式,已睡着 第一个任务执行完毕 第二个异步任务完成 主线程:我睡了3秒,我醒了 主线程:第一个任务返回Hello, world! 主线程:第二个任务返回HELLO, WORLD! 主线程:程序执行耗时:3069
Java 8允许在接口中定义默认方法,这些方法可以有实现,可以在接口的实现类中直接调用,而无需重新实现。例如:
public interface MyInterface {
default void myMethod() {
System.out.println("Default method");
}
}
public class MyClass implements MyInterface {
// 不需要实现myMethod()方法
}
MyClass obj = new MyClass();
obj.myMethod(); // 输出:Default method
接口默认方法的要求:
Java 8引入了新的Date/Time API,用于处理日期和时间。它提供了一组新的日期和时间类,如LocalDate、LocalTime、LocalDateTime等,可以更好地处理日期和时间,并提供了许多方便的方法,如计算日期间隔、格式化日期等。
例如:
LocalDate date = LocalDate.of(2022, Month.MARCH, 14);
LocalTime time = LocalTime.of(12, 30);
LocalDateTime dateTime = LocalDateTime.of(date, time);
System.out.println(dateTime); // 输出:2022-03-14T12:30
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。