JDK8特性学习笔记

1Lambda表达式

1.1标准格式

(参数列表) -> {}

方法的参数是接口类型可以考虑用Lambda表达式

无参数无返回值

public interface EatAble {
    public abstract void eat();
}
public class LambdaDemo {
    public static void main(String[] args) {
        doEat(() -> {
            System.out.println("eat food");
        });
    }

    private static void doEat(EatAble e) {
        e.eat();
    }
}

有参数有返回值

public interface DriveAble {
    public abstract String drive(String name);
}
public class LambdaDemo {
    public static void main(String[] args) {
        doDrive((String name) -> {
            System.out.println("drive " + name);
            return name;
        });
    }

    private static void doDrive(DriveAble d) {
        String car = d.drive("byd");
        System.out.println("car=" + car);
    }

}

1.2底层原理

匿名内部类:编译后生成一个新的类

Lambda表达式:编译后生成一个私有静态方法,表达式的代码会放到方法中,实际上也会生成一个匿名内部类重写抽象方法

1.3省略格式

  • 小括号内参数类型可以省略

  • 小括号只有一个参数,括号可以省略

  • 大括号只有一个语句,可以省略大括号、return、分号

1.4前提条件

  • 方法参数或局部变量为接口

  • 接口只有一个抽象方法(函数式接口)

@FunctionalInterface // 检测接口是否只有一个抽象方法
public interface EatAble {
    public abstract void eat();
}

1.5和匿名内部类对比

  • 匿名内部类需要的类型是类,抽象类,接口;Lambda需要的类型是接口

  • 匿名内部类的抽象方法数量任意;Lambda的抽象方法只有一个

  • 匿名内部类编译后形成class;Lambda运行时动态生成class

1.6接口默认方法

实现类可以不重写默认方法,也可以重写

public interface DriveAble {
    public abstract String drive(String name);

    default void print() {
        System.out.println("print");
    }
}
public class MyDrive implements DriveAble {
    @Override
    public String drive(String name) {
        return null;
    }
}

1.7接口静态方法

实现类无法重写、无法调用静态方法

public interface DriveAble {
    static void create() {
        System.out.println("create");
    }
}

1.8常用内置函数式接口

1.8.1Supplier

供给型接口

public class SupplierDemo {
    public static void main(String[] args) {
        printMax(() -> {
            int[] array = {1, 2, 3};
            Arrays.sort(array);
            return array[array.length - 1];
        });
    }

    private static void printMax(Supplier<Integer> supplier) {
        Integer value = supplier.get();
        System.out.println("value=" + value);
    }
}

1.8.2Consumer

消费型接口

public class ConsumerDemo {
    public static void main(String[] args) {
        print((String s) -> {
            System.out.println("upper case=" + s.toUpperCase());
        });
    }

    private static void print(Consumer<String> consumer) {
        consumer.accept("hello");
    }
}
public class ConsumerDemo2 {
    public static void main(String[] args) {
        print((String s) -> {
            System.out.println("upper case=" + s.toUpperCase());
        }, (String s) -> {
            System.out.println("lower case=" + s.toLowerCase());
        });
    }

    private static void print(Consumer<String> c1, Consumer<String> c2) {
        // 先调用c1后调用c2
        c1.andThen(c2).accept("Hello");
    }
}

1.8.3Function

类型转换接口

public class FunctionDemo {
    public static void main(String[] args) {
        getNumber((String s) -> {
            return Integer.parseInt(s);
        });
    }

    private static void getNumber(Function<String, Integer> function) {
        Integer num = function.apply("10");
        System.out.println(num);
    }
}
public class FunctionDemo2 {
    public static void main(String[] args) {
        getNumber((String s) -> {
            return Integer.parseInt(s);
        }, (Integer i) -> {
            return i * 5;
        });
    }

    private static void getNumber(Function<String, Integer> f1, Function<Integer, Integer> f2) {
        Integer num = f1.andThen(f2).apply("10");
        System.out.println(num);
    }
}

1.8.4Predicate

判断型接口

public class PredicateDemo {
    public static void main(String[] args) {
        isGreaterThanTen((Integer i) -> {
            return i > 10;
        });
    }

    private static void isGreaterThanTen(Predicate<Integer> predicate) {
        boolean flag = predicate.test(13);
        System.out.println(flag);
    }
}
public class PredicateDemo2 {
    public static void main(String[] args) {
        isGreaterThanTen((Integer i) -> {
            return i > 10;
        }, (Integer i) -> {
            return i < 15;
        });
    }

    private static void isGreaterThanTen(Predicate<Integer> p1, Predicate<Integer> p2) {
        boolean flag = p1.and(p2).test(13);
        System.out.println(flag);
    }
}

1.9方法引用

格式:::

常见引用方式

  • 对象::方法名

  • 类名::静态方法

  • 类名::普通方法

  • 类名::new

  • 数组::new

1.9.1对象名::引用成员方法

被引用的方法,参数要和接口中抽象方法的参数一样

接口抽象方法有返回值,被引用的方法必须有返回值

public static void main(String[] args) {
        Date date = new Date();
        Supplier<Long> supplier = date::getTime;
        System.out.println(supplier.get());
    }

1.9.2类名::静态方法

 public static void main(String[] args) {
        Supplier<Long> supplier = System::currentTimeMillis;
        System.out.println(supplier.get());
    }

1.9.3类名::引用实例方法

将第一个参数作为方法的调用者

public static void main(String[] args) {
        Function<String, Integer> function = String::length;
        System.out.println(function.apply("hello"));
    }
public static void main(String[] args) {
        BiFunction<String, Integer, String> biFunction = String::substring;
        System.out.println(biFunction.apply("hello", 1));
    }

1.9.4类名::new引用构造方法

public class Person {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public static void main(String[] args) {
        Supplier<Person> supplier = Person::new;
        System.out.println(supplier.get());
    }

1.9.5数组::new引用数组构造方法

public static void main(String[] args) {
        Function<Integer, int[]> function = int[]::new;
        int[] array = function.apply(5);
        System.out.println(Arrays.toString(array));
    }

2Stream流操作

类似于生产流水线,不是一种数据结构,不保存数据,只是对数据加工

2.1获取Stream

根据Collection获取

List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();

Stream.of获取

基本类型的数组不可用

String[] strings = new String[]{"123", "456"};
Stream<String> stream1 = Stream.of(strings);

2.2注意事项

Stream只能操作一次

Stream方法返回的是新的流

Stream不调用终结方法,中间操作不会执行

2.3常用方法

2.3.1forEach遍历

List<String> list = new ArrayList<>();
Collections.addAll(list, "123", "456");
list.stream().forEach(System.out::println);

2.3.2count统计

List<String> list = new ArrayList<>();
Collections.addAll(list, "123", "456");
System.out.println(list.stream().count());

2.3.3filter过滤

List<String> list = new ArrayList<>();
Collections.addAll(list, "123", "456", "78");
list.stream().filter(s -> s.length() == 2).forEach(System.out::println)

2.3.4limit截取

List<String> list = new ArrayList<>();
Collections.addAll(list, "123", "456", "78");
list.stream().limit(2).forEach(System.out::println);

2.3.5skip跳过

List<String> list = new ArrayList<>();
Collections.addAll(list, "123", "456", "78");
list.stream().skip(2).forEach(System.out::println);

2.3.6map映射

List<String> list = new ArrayList<>();
Collections.addAll(list, "123", "456", "78");
list.stream().map(Integer::parseInt).forEach(System.out::println);

2.3.7sorted排序

List<Integer> list = new ArrayList<>();
Collections.addAll(list, 123, 456, 78);
list.stream().sorted((i1, i2) -> i2 - i1).forEach(System.out::println);

2.3.8distinct去重

List<Integer> list = new ArrayList<>();
Collections.addAll(list, 123, 456, 78, 123);
list.stream().distinct().forEach(System.out::println);

如果Stream是自定义类型,需要重写equals, hashCode方法

2.3.9match匹配

allMatch全部匹配

anyMatch任意匹配

nonMatch全部不匹配

List<Integer> list = new ArrayList<>();
Collections.addAll(list, 123, 456, 78, 123);
System.out.println(list.stream().allMatch(i -> i > 0));

2.3.10find查找

List<Integer> list = new ArrayList<>();
Collections.addAll(list, 123, 456, 78, 123);
Optional<Integer> first = list.stream().findFirst();
System.out.println(first.get());

2.3.11max,min最大最小

List<Integer> list = new ArrayList<>();
Collections.addAll(list, 123, 456, 78, 123);
Optional<Integer> max = list.stream().max((i1, i2) -> i1 - i2);
System.out.println(max.get());

2.3.12reduce归纳

List<Integer> list = new ArrayList<>();
Collections.addAll(list, 1, 2, 3, 4);
Integer reduce = list.stream().reduce(0, (a, b) -> a + b);
System.out.println(reduce);

2.3.13mapToInt转为int

List<Integer> list = new ArrayList<>();
Collections.addAll(list, 1, 2, 3, 4);
list.stream().mapToInt(Integer::intValue).filter(i -> i > 2).forEach(System.out::println);

2.3.14concat合并

合并后不能操作之前的流

List<Integer> list = new ArrayList<>();
Collections.addAll(list, 1, 2);
List<Integer> list2 = new ArrayList<>();
Collections.addAll(list2, 3, 4);
Stream.concat(list.stream(), list2.stream()).forEach(System.out::println);

2.4收集结果

2.4.1收集到集合、数组

Stream<String> stream = Stream.of("123", "456");
List<String> list = stream.collect(Collectors.toList());
Stream<String> stream = Stream.of("123", "456");
String[] array = stream.toArray(String[]::new);

2.4.2聚合

最大值:maxBy

最小值:minBy

平均:averagingInt

求和:summingInt

统计:counting

Stream<Student> stream = Stream.of(new Student(10), new Student(20));
Optional<Student> max = stream.collect(Collectors.maxBy((s1, s2) -> s1.getAge() - s2.getAge()));
System.out.println(max.get());

2.4.3分组

Stream<Student> stream = Stream.of(new Student(10), new Student(10), new Student(20));
Map<Integer, List<Student>> map = stream.collect(Collectors.groupingBy(Student::getAge));
map.forEach((k, v) -> System.out.println("k=" + k + ",v=" + v));

多级分组

Stream<Student> stream = Stream.of(new Student(10, "male"), new Student(10, "female"), new Student(20, "male"));
Map<Integer, Map<String, List<Student>>> map = stream.collect(Collectors.groupingBy(Student::getAge, Collectors.groupingBy(Student::getGender)));
map.forEach((k ,v) -> {
    System.out.println("k=" + k);
    v.forEach((k2, v2) -> System.out.println("k2=" + k2 + ",v2=" + v2));
});

2.4.4分区

Stream<Student> stream = Stream.of(new Student(10), new Student(10), new Student(20));
Map<Boolean, List<Student>> map = stream.collect(Collectors.partitioningBy(s -> s.getAge() > 15));
map.forEach((k, v) -> System.out.println("k=" + k + ",v=" + v));

2.4.5拼接

Stream<Student> stream = Stream.of(new Student(10, "male"), new Student(10, "female"), new Student(20, "male"));
String string = stream.map(Student::getGender).collect(Collectors.joining(","));
System.out.println(string);

2.5并行Stream流

多线程处理

2.5.1获取并行流

List<Integer> list = new ArrayList<>();
// 直接获取
Stream<Integer> parallelStream = list.parallelStream();
// 串行转并行
Stream<Integer> parallelStream2 = Stream.of(1, 2, 3, 4, 5).parallel();

2.5.2线程安全

加同步代码块

List<Integer> list = new ArrayList<>();
Object obj = new Object();
IntStream.rangeClosed(1, 1000).parallel().forEach(i -> {
    synchronized (obj) {
        list.add(i);
    }
});
System.out.println(list.size());

使用线程安全集合

Vector<Integer> list = new Vector<>();
Object obj = new Object();
IntStream.rangeClosed(1, 1000).parallel().forEach(i -> {
    list.add(i);
});
System.out.println(list.size());
List<Integer> list2 = new ArrayList<>();
List<Integer> synchronizedList = Collections.synchronizedList(list2);

使用collect/toArray

List<Integer> list = IntStream.rangeClosed(1, 1000).parallel().boxed().collect(Collectors.toList());
System.out.println(list.size());

2.5.3Fork/Join框架

分治,一个大任务拆分成很多小任务异步执行

工作窃取算法

2.6Optional

防止空指针异常

创建Optional对象

Optional<String> o1 = Optional.of("123");
Optional<Object> o2 = Optional.ofNullable(null);
Optional<Object> o3 = Optional.empty();

获取值

Optional<String> o1 = Optional.of("123");
if (o1.isPresent()) {
    System.out.println(o1.get());
}

其它方法

Optional<Object> o2 = Optional.ofNullable(null);
String s = (String) o2.orElse("45");

Optional<String> o1 = Optional.of("123");
o1.ifPresent(str -> System.out.println("has value"));

Optional<String> o4 = Optional.of("ABC");
System.out.println(o4.map(String::toLowerCase).get());

3日期时间API

旧版日期时间API存在设计不合理、非线程安全、时区处理麻烦等问题

3.1日期时间类

LocalDate

LocalDate now = LocalDate.now();
LocalDate localDate = LocalDate.of(2024, 6, 1);

LocalTime

LocalTime now = LocalTime.now();
LocalTime localTime = LocalTime.of(14, 10, 10);

LocalDateTime

LocalDateTime now = LocalDateTime.now();
LocalDateTime localDateTime = LocalDateTime.of(2024, 1, 1, 10, 10, 9);

修改

LocalDateTime now = LocalDateTime.now();
System.out.println(now.withHour(20));

增加或减少

LocalDateTime now = LocalDateTime.now();
System.out.println(now.plusYears(1));
System.out.println(now.minusDays(10));

比较

LocalDateTime now = LocalDateTime.now();
LocalDateTime localDateTime = LocalDateTime.of(2024, 1, 1, 10, 10, 9);
System.out.println(now.isAfter(localDateTime));
System.out.println(now.isBefore(localDateTime));
System.out.println(now.isEqual(localDateTime));

3.2时间格式化与解析

LocalDateTime now = LocalDateTime.now();
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(now.format(dtf));
System.out.println(LocalDateTime.parse("2024-01-01 10:00:00", dtf));

3.3Instant

表示时间戳

Instant now = Instant.now();
System.out.println(now);
System.out.println(now.plusSeconds(10));
System.out.println(now.minusSeconds(5));
System.out.println(now.getNano());

3.4日期时间差

后面减去前面

时间差

LocalTime now = LocalTime.now();
LocalTime localTime = LocalTime.of(23, 10, 10);
Duration duration = Duration.between(now, localTime);
System.out.println(duration.toHours());
System.out.println(duration.toMinutes());
System.out.println(duration.getSeconds());

日期差

LocalDate now = LocalDate.now();
LocalDate localDate = LocalDate.of(2024, 6, 1);
Period period = Period.between(localDate, now);
System.out.println(period.getYears());
System.out.println(period.getMonths());
System.out.println(period.getDays());

3.5时间调整

LocalDateTime now = LocalDateTime.now();
System.out.println(now.with(TemporalAdjusters.firstDayOfNextYear()));

3.6设置时区

获取所有时区

Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();

标准时区

ZonedDateTime.now(Clock.systemUTC())

默认时区

ZonedDateTime.now()

指定时区

ZonedDateTime.now(ZoneId.of("Asia/Shanghai"))

修改时区、时间

ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
zonedDateTime.withZoneSameInstant(ZoneId.of("Europe/Monaco"))

修改时区、不改时间

ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
zonedDateTime.withZoneSameLocal(ZoneId.of("Europe/Monaco"))

4重复注解与类型注解

4.1重复注解

@Config("abc")
@Config("def")
public class RepeatAnnotationDemo {
    public static void main(String[] args) {
        Config[] annotations = RepeatAnnotationDemo.class.getAnnotationsByType(Config.class);
        for (Config config : annotations) {
            System.out.println(config);
        }
    }
}

@Retention(RetentionPolicy.RUNTIME)
@interface Configs {
    Config[] value();
}

@Repeatable(Configs.class)
@Retention(RetentionPolicy.RUNTIME)
@interface Config {
    String value();
}

4.2类型注解

@Target元注解新增了两种类型

TYPE_PARAMETER:可以写在类型参数的声明语句

public class TypeAnnotationDemo<@Type T> {
}

@Target(ElementType.TYPE_PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@interface Type {
}

TYPE_USE:可以在任何用到类型的地方使用

public class TypeAnnotationDemo {
    @Type2
    private int i = 5;
    
    public int sum(@Type2 int a, @Type2 int b) {
        return a + b;
    }
}

@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface Type2 {
}

源码仓库:gitee

  • 29
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值