赞
踩
目录
使用前提:
练习一
代码如下:
- public interface Eatable {
- void eat();
- }
- public class EatableDemo {
- public static void main(String[] args) {
- useEatable(() -> {
- System.out.println("一天一苹果,医生远离我");
- });
- }
-
- private static void useEatable(Eatable e) {
- e.eat();
- }
- }
运行结果:
练习二
代码如下:
- public interface Flyable {
- void fly(String s);
- }
- public class FlyableDemo {
- public static void main(String[] args) {
- useFlyable((String s) -> {
- System.out.println(s);
- });
- }
-
- public static void useFlyable(Flyable f) {
- f.fly("风和日丽,晴空万里");
- }
- }
运行结果:
练习三
代码如下:
- public interface Addable {
- int add(int x, int y);
- }
- public class AddableDemo {
- public static void main(String[] args) {
- useAddable((int x, int y) -> {
- return x + y;
- });
- }
-
- public static void useAddable(Addable a) {
- int sum = a.add(10, 20);
- System.out.println(sum);
- }
- }
运行结果:
省略规则:
注意事项:
所需类型不同
使用限制不同
实现原理不同
方法引用符
推导与省略
常见的引用方法:
引用类方法,其实就是引用类的静态方法
练习:
代码如下:
- public interface Converter {
- int convert(String s);
- }
- public class ConverterDemo {
- public static void main(String[] args) {
- useConverter(Integer::parseInt);
- }
-
- private static void useConverter(Converter c) {
- int number = c.convert("665") + 1;
- System.out.println(number);
- }
- }
运行结果:
引用对象的实例方法,其实就是引用类中的成员方法
练习:
代码如下:
- public class PrintString {
- public void printUpper(String s) {
- System.out.println(s.toUpperCase());
- }
- }
- public interface Printer {
- void printUpperCase(String s);
- }
- public class PrinterDemo {
- public static void main(String[] args) {
- PrintString ps = new PrintString();
- usePrinter(ps::printUpper);
- }
-
- private static void usePrinter(Printer p) {
- p.printUpperCase("helloWorld");
- }
- }
运行结果:
引用类的实例方法,其实就是引用类中的成员方法
练习:
代码如下:
- public interface MyString {
- String mySubString(String s, int x, int y);
- }
- public class MyStringDemo {
- public static void main(String[] args) {
- useMyString(String::substring);
- }
-
- private static void useMyString(MyString my) {
- String s = my.mySubString("HelloWorld", 2, 5);
- System.out.println(s);
- }
- }
运行结果:
引用构造器,其实就是引用构造方法
练习:
代码如下:
- public class Student {
- private String name;
- private int age;
-
- // 省略get/set/满参构造方法
- }
- public interface StudentBuilder {
- Student build(String name, int age);
- }
- public class StudentDemo {
- public static void main(String[] args) {
- useStudentBuilder(Student::new);
- }
-
- private static void useStudentBuilder(StudentBuilder sb) {
- Student student = sb.build("张三", 18);
- System.out.println(student.getName() + "," + student.getAge());
- }
- }
运行结果:
函数式接口:有且仅有一个抽象方法的接口
如何检测一个接口是不是函数式接口呢?
注意:
需求:
代码如下:
- public class RunnableDemo {
- public static void main(String[] args) {
- startThread(() -> System.out.println(Thread.currentThread().getName() + " 线程启动了"));
- }
-
- private static void startThread(Runnable r) {
- new Thread(r).start();
- }
- }
运行结果:
需求:
代码如下:
- public class ComparatorDemo {
- public static void main(String[] args) {
- ArrayList<String> array = new ArrayList<>();
- array.add("ccc");
- array.add("aa");
- array.add("b");
- array.add("ddd");
-
- System.out.println("排序前: " + array);
-
- array.sort(getComparator());
- System.out.println("排序后: " + array);
- }
-
- private static Comparator<String> getComparator() {
- // 如果方法的返回值是一个函数式接口,我们可以使用 Lambda 表达式作为结果返回
- return (s1, s2) -> s2.length() - s1.length();
- }
- }
运行效果:
Java 8 在 java.util.function 包下与定义了大量的函数式接口供我们使用
我们重点来学习下面的 4 个接口
Supplier<T>:包含一个无参的方法:
练习:
代码如下:
- public class SupplierTest {
- public static void main(String[] args) {
- int[] arr = {1, 3, 4, 5, 2};
-
- int max = getMax(() -> {
- Arrays.sort(arr);
- return arr[arr.length - 1];
- });
- System.out.println(max);
- }
-
- private static int getMax(Supplier<Integer> sup) {
- return sup.get();
- }
- }
运行效果:
Consumer<T>:包含两个方法
练习:
代码如下:
- public class ConsumerTest {
- public static void main(String[] args) {
- operatorString(s1 -> System.out.print("姓名: " + s1.split(",")[0] + ", "), s2 -> System.out.println("年龄: " + s2.split(",")[1]));
- }
-
- private static void operatorString(Consumer<String> con1, Consumer<String> con2) {
- String[] strArray = {"林青霞,30", "张曼玉,35", "王祖贤,33"};
- for (String s : strArray) {
- con1.andThen(con2).accept(s);
- }
- }
- }
运行效果:
Predicate<T>:常用的四个方法
练习:
- public class PredicateDemo01 {
- public static void main(String[] args) {
- boolean b1 = checkString1(s -> s.length() > 8);
- System.out.println("b1: " + b1);
-
- boolean b2 = checkString2(s -> s.length() > 8);
- System.out.println("b2: " + b2);
-
- boolean b3 = checkString3(s -> s.contains("hello"), s -> s.length() > 5);
- System.out.println("b3: " + b3);
-
- boolean b4 = checkString4(s -> s.contains("hello"), s -> s.length() > 20);
- System.out.println("b4: " + b4);
- }
-
- // 判断给定的字符串是否满足要求
- private static boolean checkString1(Predicate<String> pre) {
- return pre.test("hello");
- }
-
- private static boolean checkString2(Predicate<String> pre) {
- return pre.negate().test("hello");
- }
-
-
- // 同一个字符串给出两个不同的判断条件,最后把这两个判断的结果做逻辑与运算的结果作为最终的结果
- private static boolean checkString3(Predicate<String> pre1, Predicate<String> pre2) {
- String s = "hello,world";
- return pre1.and(pre2).test(s);
- }
-
- private static boolean checkString4(Predicate<String> pre1, Predicate<String> pre2) {
- String s = "hello,world";
- return pre1.or(pre2).test(s);
- }
- }
运行结果:
Function<T,R>:常用的两个方法
练习:
代码如下:
- public class FunctionTest {
- public static void main(String[] args) {
- convert1(s -> s.split(",")[1], Integer::parseInt, i -> i + 70);
- }
-
- private static void convert1(Function<String, String> fun1, Function<String, Integer> fun2, Function<Integer, Integer> fun3) {
- String s = "林青霞,30";
- Integer i = fun1.andThen(fun2).andThen(fun3).apply(s);
- System.out.println(i);
- }
- }
运行结果:
Stream 流的常见生成方式
代码如下:
- @Test
- public void test01() {
- ArrayList<Object> list = new ArrayList<>();
- Stream<Object> stream1 = list.stream(); // 串行流
- Stream<Object> stream2 = list.parallelStream(); // 并行流
- }
- @Test
- public void test02() {
- String[] arr1 = {"hello", "world"};
- Stream<String> stream1 = Arrays.stream(arr1);
-
- int[] arr2 = {1, 2, 3};
- IntStream stream2 = Arrays.stream(arr2);
- }
- @Test
- public void test03() {
- Stream<Integer> stream = Stream.of(1, 2, 3);
- }
- @Test
- public void test04() {
- Stream<Integer> stream1 = Stream.iterate(0, x -> x + 2).limit(10);
- Stream<Double> stream2 = Stream.generate(() -> Math.random() + 10).limit(10);
- }
代码如下:
- @Test
- public void test() {
- int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- // 保留偶数
- Arrays.stream(arr).filter(x -> x % 2 == 0).forEach(System.out::println);
- }
运行结果:
- @Test
- public void test() {
- int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- // 截取前三个元素
- Arrays.stream(arr).limit(3).forEach(System.out::println);
- }
运行结果:
- @Test
- public void test() {
- int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- // 跳过前三个元素
- Arrays.stream(arr).skip(3).forEach(System.out::println);
- }
运行结果:
- @Test
- public void test() {
- int[] arr = {1, 1, 2, 2, 3, 3};
- Arrays.stream(arr).distinct().forEach(System.out::println);
- }
运行结果:
- @Test
- public void test() {
- int[] arr = {1, 2, 3};
- IntStream stream = Arrays.stream(arr);
- stream.peek(n -> System.out.println(n + 10)).count();
- }
运行结果:
- @Test
- public void test() {
- String[] numbers = {"1", "2", "3"};
- Stream<Integer> stream = Arrays.stream(numbers).map(Integer::parseInt);
- }
- @Test
- public void test() {
- // 类似的还有mapToLong、mapToDouble
- String[] number = {"1", "2", "3"};
- IntStream stream = Arrays.stream(number).mapToInt(Integer::parseInt);
- }
- @Test
- public void test() {
- class User {
- public String[] hobby;
-
- public User(String[] hobby) {
- this.hobby = hobby;
- }
- }
-
- ArrayList<User> list = new ArrayList<>();
- Collections.addAll(list, new User("溜冰,滑雪,篮球".split(",")), new User("乒乓球,足球,网球".split(",")));
-
- Stream<String> stream = list.stream().flatMap(user -> Arrays.stream(user.hobby));
- stream.forEach(System.out::println);
- }
运行结果:
- @Test
- public void test() {
- class Number {
- public int[] nums;
-
- public Number(int[] nums) {
- this.nums = nums;
- }
- }
-
- ArrayList<Number> list = new ArrayList<>();
- Collections.addAll(list, new Number(new int[]{1, 2, 3}), new Number(new int[]{4, 5, 6}));
-
- // 类似的还有flatMapToLong、flatMapToDouble
- IntStream stream = list.stream().flatMapToInt(n -> Arrays.stream(n.nums));
- stream.forEach(System.out::println);
- }
运行结果:
- @Test
- public void test() {
- Stream.of(3, 1, 2).sorted().forEach(System.out::println);
- }
运行结果:
- @Test
- public void test() {
- class Student {
- public String name;
- public int chinese;
- public int mathematics;
- public int english;
-
- // 省略满参构造和toString方法
- }
-
- ArrayList<Student> list = new ArrayList<>();
- Collections.addAll(list, new Student("lisi", 90, 85, 70), new Student("zhangsan", 90, 85, 60), new Student("wangwu", 99, 75, 75));
-
- // 如果语文成绩相等,就比较数学成绩,如果数学成绩相等,就比较英语成绩
- list.stream().sorted((n1, n2) -> n1.chinese == n2.chinese ? n1.mathematics == n2.mathematics ? n1.english - n2.english : n1.mathematics - n2.mathematics : n1.chinese - n2.chinese).forEach(System.out::println);
- }
运行结果:
- @Test
- public void test() {
- Stream<Integer> stream1 = Stream.of(1, 2, 3);
- Stream<Integer> stream2 = Stream.of(3, 2, 1);
-
- Stream.concat(stream1, stream2).forEach(System.out::println);
- }
运行结果:
- @Test
- public void test() {
- Stream<Integer> parallelStream = Stream.of(1, 2, 3).parallel();
- }
- @Test
- public void test() {
- int[] arr = {1, 2, 3};
-
- System.out.println(Arrays.stream(arr).isParallel()); // 串行流
- System.out.println(Arrays.stream(arr).parallel().isParallel()); // 并行流
- }
运行结果:
- @Test
- public void test() {
- ArrayList<Integer> list = new ArrayList<>();
- Stream<Integer> stream = list.parallelStream().sequential();
- System.out.println(stream.isParallel());
- }
运行结果:
- @Test
- public void test() {
- ArrayList<Integer> arrayList = new ArrayList<>();
- Collections.addAll(arrayList, 1, 2, 3);
-
- Stream<Integer> stream1 = arrayList.stream().unordered();
- stream1.forEach(System.out::println); // 输出 1 2 3
- System.out.println();
-
- // unordered()方法并不能保证输出的结果一定是无序的,而只是告诉Stream类,在进行后续操作时,可以不保留元素的原始顺序,以提高并行处理性能。
- LinkedList<Object> linkedList = new LinkedList<>();
- Collections.addAll(linkedList, 1, 2, 3);
- Stream<Object> stream2 = linkedList.stream().unordered();
- stream2.forEach(System.out::println);
- }
运行结果:
代码如下:
- @Test
- public void test() {
- Stream.of(1, 2, 3).forEach(System.out::println);
- }
运行结果:
- @Test
- public void test() {
- Integer[] arr = Stream.of(1, 2, 3).toArray(Integer[]::new);
- }
- @Test
- public void test() {
- long count = Stream.of(1, 2, 3).count();
- System.out.println(count);
- }
运行结果:
- @Test
- public void test() {
- ArrayList<String> list = new ArrayList<>();
- int sum1 = list.stream().mapToInt(Integer::valueOf).sum();
- long sum2 = list.stream().mapToLong(Long::valueOf).sum();
- double sum3 = list.stream().mapToDouble(Double::valueOf).sum();
- }
- @Test
- public void test() {
- boolean b = Stream.of(1, 2, 3).anyMatch(n -> n == 2);
- System.out.println(b);
- }
运行结果:
- @Test
- public void test() {
- boolean b = Stream.of(1, 2, 3).allMatch(n -> n == 2);
- System.out.println(b);
- }
运行结果:
- @Test
- public void test() {
- boolean b = Stream.of(1, 2, 3).allMatch(n -> n != 0);
- System.out.println(b);
- }
运行结果:
- @Test
- public void test() {
- class User {
- public String name;
- public int age;
-
- public User(String name, int age) {
- this.name = name;
- this.age = age;
- }
- }
-
- ArrayList<User> list = new ArrayList<>();
- Collections.addAll(list, new User("zhangsan", 2), new User("lisi", 1), new User("wangwu", 3));
-
- Optional<User> maxOptional = list.stream().max((n1, n2) -> n1.age - n2.age);
- System.out.println(maxOptional.get().name + " " + maxOptional.get().age);
- }
运行结果:
- @Test
- public void test() {
- class User {
- public String name;
- public int age;
-
- public User(String name, int age) {
- this.name = name;
- this.age = age;
- }
- }
-
- ArrayList<User> list = new ArrayList<>();
- Collections.addAll(list, new User("zhangsan", 2), new User("lisi", 1), new User("wangwu", 3));
-
- Optional<User> maxOptional = list.stream().min((n1, n2) -> n1.age - n2.age);
- System.out.println(maxOptional.get().name + " " + maxOptional.get().age);
- }
运行结果:
- @Test
- public void test() {
- Optional<Integer> optional = Stream.of(1, 2, 3, 4, 5, 6, 7).parallel().filter(i -> i % 2 == 0).findAny();
- System.out.println(optional.get());
- }
运行结果:
- @Test
- public void test() {
- Optional<Integer> optional = Stream.of(1, 2, 3).findFirst();
- System.out.println(optional.get());
- }
运行结果:
- @Test
- public void test() {
- Iterator<Integer> iterator = Stream.of(1, 2, 3).iterator();
- while (iterator.hasNext()) {
- System.out.println(iterator.next());
- }
- }
运行结果:
- @Test
- public void test1() {
- // Optional reduce(BinaryOperator accumulator)
- Integer[] arr = {1, 2, 3};
- Optional<Integer> optional = Arrays.stream(arr).reduce((n1, n2) -> n1 + n2);
- System.out.println("sum: " + optional.get());
- }
-
- @Test
- public void test2() {
- // T reduce(T identity, BinaryOperator accumulator)
- Integer[] arr = {1, 2, 3};
- Integer sum1 = Arrays.stream(arr).reduce(0, (n1, n2) -> n1 + n2);
- Integer sum2 = Arrays.stream(arr).reduce(10, (n1, n2) -> n1 + n2);
- System.out.println("sum1: " + sum1);
- System.out.println("sum2: " + sum2);
- }
运行结果:
对数据使用 Stream 流的方式操作完毕后,我想把流中的数据收集到集合中,该怎么办呢?
Stream 流的收集方法
工具类 Collectors 提供了具体的收集方法
代码如下:
- @Test
- public void test() {
- String[] arr = {"1", "1", "2", "2", "3", "3"};
- List<Integer> list = Arrays.stream(arr).map(Integer::valueOf).map(n -> n + 10).collect(Collectors.toList());
- System.out.println(list);
- }
运行结果:
- @Test
- public void test() {
- String[] arr = {"1", "1", "2", "2", "3", "3"};
- Set<Integer> set = Arrays.stream(arr).map(Integer::valueOf).map(n -> n + 10).collect(Collectors.toSet());
- System.out.println(set);
- }
运行结果:
- @Test
- public void test() {
- String[] arr = {"1", "2", "3"};
- Map<String, String> map = Arrays.stream(arr).map(Integer::valueOf).map(n -> n + 10).collect(Collectors.toMap(n -> "key: " + n, n -> "value: " + n));
- System.out.println(map);
- }
运行结果:
- @Test
- public void test() {
- String[] arr = {"1", "2", "3"};
- ArrayList<Integer> arrayList = Arrays.stream(arr).map(Integer::valueOf).map(n -> n + 10).collect(Collectors.toCollection(ArrayList::new));
- LinkedList<Integer> linkedList = Arrays.stream(arr).map(Integer::valueOf).map(n -> n + 10).collect(Collectors.toCollection(LinkedList::new));
- }
- @Test
- public void test() {
- String[] arr = {"1", "2", "3"};
- Long count = Arrays.stream(arr).collect(Collectors.counting());
- System.out.println(count);
- }
运行结果:
- @Test
- public void test() {
- class User {
- public String name;
- public int age;
-
- public User(String name, int age) {
- this.name = name;
- this.age = age;
- }
- }
-
- User[] users = {new User("jack", 18), new User("tom", 19), new User("rose", 20)};
- // 类似的还有summingDouble、summingLong
- Integer sum = Arrays.stream(users).collect(Collectors.summingInt(user -> user.age));
- System.out.println(sum);
- }
运行结果:
- @Test
- public void test() {
- class User {
- public String name;
- public int age;
-
- public User(String name, int age) {
- this.name = name;
- this.age = age;
- }
- }
-
- User[] users = {new User("jack", 18), new User("tom", 19), new User("rose", 20)};
- // 类似的还有averagingDouble、averagingLong
- Double avg = Arrays.stream(users).collect(Collectors.averagingInt(user -> user.age));
- System.out.println(avg);
- }
运行结果:
- @Test
- public void test() {
- class User {
- public String name;
- public int age;
-
- public User(String name, int age) {
- this.name = name;
- this.age = age;
- }
- }
-
- ArrayList<User> list = new ArrayList<>();
- Collections.addAll(list, new User("jack", 18), new User("tom", 19), new User("rose", 20));
- // 类似的还有 summarizingDouble、summarizingLong
- IntSummaryStatistics intSummaryStatistics = list.stream().collect(Collectors.summarizingInt(u -> u.age));
- System.out.println(intSummaryStatistics);
- }
运行结果:
- @Test
- public void test() {
- class User {
- public String name;
- public int age;
-
- public User(String name, int age) {
- this.name = name;
- this.age = age;
- }
- }
-
- ArrayList<User> list = new ArrayList<>();
- Collections.addAll(list, new User("jack", 18), new User("tom", 19), new User("rose", 20));
- String str = list.stream().map(u -> u.name).collect(Collectors.joining());
- System.out.println(str);
- }
运行结果:
- @Test
- public void test() {
- Optional<Integer> optional = Stream.of(2, 3, 1).collect(Collectors.maxBy((n1, n2) -> n1 - n2));
- System.out.println(optional.get());
- }
运行结果:
- @Test
- public void test() {
- Optional<Integer> optional = Stream.of(2, 3, 1).collect(Collectors.minBy((n1, n2) -> n1 - n2));
- System.out.println(optional.get());
- }
运行结果:
- @Test
- public void test() {
- Integer sum = Stream.of(1, 2, 3).collect(Collectors.reducing(0, Integer::sum));
- System.out.println(sum);
- }
运行结果:
- @Test
- public void test() {
- Integer size = Stream.of(1, 2, 3).collect(Collectors.collectingAndThen(Collectors.toList(), list -> list.size()));
- System.out.println(size);
- }
运行结果:
- @Test
- public void test() {
- Map<Integer, List<Integer>> map = Stream.of(1, 2, 3).collect(Collectors.groupingBy(n -> n));
- System.out.println(map);
- }
运行结果:
- @Test
- public void test() {
- Map<Boolean, List<Integer>> map = Stream.of(1, 2, 3).collect(Collectors.partitioningBy(n -> n % 2 == 0));
- System.out.println(map);
- }
运行结果:
我们在编写代码的时候出现最多的就是空指针异常。所以在很多情况下我们需要做各种非空的判断。例如:
- if (xxx!=null){
-
- }
而过多的判断语句会让我们的代码显得臃肿不堪。
所以在 JDK8 引入了 Optional,养成使用 Optional 的习惯后你可以写出更优雅的代码来避免空指针异常。
代码如下:
- Cat cat = new Cat("tom", 3);
-
- Optional<Cat> optionalCat1 = Optional.of(cat);
- Optional<Cat> optionalCat2 = Optional.empty();
- Optional<Cat> optionalCat3 = Optional.ofNullable(cat);
代码如下:
- Cat cat = new Cat("tom", 3);
-
- Optional<Cat> optionalCat = Optional.ofNullable(cat);
- optionalCat.ifPresent(s -> System.out.println("name: " + s.getName()));
运行结果:
代码如下:
- System.out.println(Optional.ofNullable(new Cat("tom", 3)).get());
- System.out.println(Optional.ofNullable(null).get());
运行结果:
- System.out.println(Optional.ofNullable(new Cat("tom", 3)).orElse(new Cat("rose", 4)));
- System.out.println(Optional.ofNullable(null).orElse(new Cat("rose", 4)));
运行结果:
- System.out.println(Optional.ofNullable(new Cat("tom", 3)).orElseGet(() -> new Cat("rose", 4)));
- System.out.println(Optional.ofNullable(null).orElseGet(() -> new Cat("rose", 4)));
运行结果:
- System.out.println(Optional.ofNullable(new Cat("tom", 3)).orElseThrow(() -> new RuntimeException("cat为空")));
- System.out.println(Optional.ofNullable(null).orElseThrow(() -> new RuntimeException("cat为空")));
运行结果:
我们可以使用 filer 方法对数据进行过滤。如果原本是有数据的,但是不符合判断,也会变成一个无数据的 Optional 对象
代码如下:
Optional.ofNullable(new Cat("tom", 3)).filter(c -> c.getAge() > 5).ifPresent(System.out::println);
运行结果:
代码如下:
System.out.println(Optional.ofNullable(null).isPresent());
运行结果:
代码如下:
- @Test
- public void test() {
- String str = "hello";
-
- // map() 方法用于将 Optional 对象中的值进行转换,而 flatMap() 方法用于将 Optional 对象中的值进行转换,并返回一个包含值的 Optional 对象
- Optional<String> s1 = Optional.ofNullable(str).map(String::toUpperCase);
- Optional<String> s2 = Optional.ofNullable(str).flatMap(s -> Optional.of(s.toUpperCase()));
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。