文章目录
- 1Lambda表达式
- 1.1标准格式
- 1.2底层原理
- 1.3省略格式
- 1.4前提条件
- 1.5和匿名内部类对比
- 1.6接口默认方法
- 1.7接口静态方法
- 1.8常用内置函数式接口
- 1.8.1Supplier
- 1.8.2Consumer
- 1.8.3Function
- 1.8.4Predicate
- 1.9方法引用
- 1.9.1对象名::引用成员方法
- 1.9.2类名::静态方法
- 1.9.3类名::引用实例方法
- 1.9.4类名::new引用构造方法
- 1.9.5数组::new引用数组构造方法
- 2Stream流操作
- 2.1获取Stream
- 2.2注意事项
- 2.3常用方法
- 2.3.1forEach遍历
- 2.3.2count统计
- 2.3.3filter过滤
- 2.3.4limit截取
- 2.3.5skip跳过
- 2.3.6map映射
- 2.3.7sorted排序
- 2.3.8distinct去重
- 2.3.9match匹配
- 2.3.10find查找
- 2.3.11max,min最大最小
- 2.3.12reduce归纳
- 2.3.13mapToInt转为int
- 2.3.14concat合并
- 2.4收集结果
- 2.4.1收集到集合、数组
- 2.4.2聚合
- 2.4.3分组
- 2.4.4分区
- 2.4.5拼接
- 2.5并行Stream流
- 2.5.1获取并行流
- 2.5.2线程安全
- 2.5.3Fork/Join框架
- 2.6Optional
- 3日期时间API
- 3.1日期时间类
- 3.2时间格式化与解析
- 3.3Instant
- 3.4日期时间差
- 3.5时间调整
- 3.6设置时区
- 4重复注解与类型注解
- 4.1重复注解
- 4.2类型注解
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 {@Overridepublic 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后调用c2c1.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 {@Type2private 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