Lambda
1. lambda的基本结构
(param1,param2,param3) -> {body}
1. 如果参数只有1个,()可以省略
2. 如果body只有一条语句,{}可以省略
3. 如果body直接return 可以{}+return一起省略
2. 函数式接口:
1. 如果一个接口只有1个抽象方法,那么该接口就是一个函数式接口。
2. 如果在接口上声明@FunctionalInterface注解,那么编译器就会按照函数式接口定义要求该接口。
3. 如果某个接口只有一个抽象方法,但并没有声明@FunctionalInterface注解,那么编译器依旧会将其看做函数式接口。
example
public class Test1 {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4,5,6);
list.forEach(i -> System.out.println(i));
new Thread(()-> System.out.println("123"));
Collections.sort(list,(o1,o2)->o2.compareTo(o1));
System.out.println(list);
}
}
Funcation
1. Funcation接口定义两个泛型,调用apply方法,可以通过第一个参数获取第二个参数
2. example: Funcation<Integer,String> funcation = a -> "hello"+a;
3. 参数或返回值为函数的方法称为高阶函数。
4. Funcation有compose和andThen两种组合函数方法: f1.compose(f2) 先执行f2函数,在执行f1 ,andThen相反
5. BiFuncation可以通过俩参数,得到一个结果,含有andThen方法,将结果拼接其他Funcation
6. BinaryOperator是BiFuncation的一种特殊实现,三个泛型类型一致,用于计算
7. example: BiFuncation<Integer,Integer,Integer> bf = (a,b) -> a+b;
或者 BiFuncation<Integer,Integer,Integer> bf = (a,b) ->{return a+b;} 调用apply时,即可通过a b获取计算后的值
8. Predicate<T>,调用test判断结果是否为true
9. example Predicate<String> predicate = a -> a.length()>3; System.out.println(predicate.test("aa"));
10. Predicate还存在and和or方法,等效于&&,|| negate 等效于 !
11. Consumer 等于单参无返回值的函数
12. Supplier 不接受参数返回结果
example
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Predicate<Integer> predicate = a -> a>3;
list.stream().filter(predicate.and(a->a%2 == 0)).forEach(System.out::println);
}
Optional
1. Optional没有实现序列化,因此不要作为返回值和参数
语法
public static void main(String[] args) {
Optional<String> optional = Optional.empty();//建立空对象
Optional<String> optional2 = Optional.of("aaa"); //建立aaa的Optional对象 of传null时,直接报NPE
Object obj = null;
Optional<Object> optional3 = Optional.ofNullable(obj);//不确定是否为null时,使用ofNullable
System.out.println(optional.isPresent()); //是否存在 empty返回false
System.out.println(optional2.get());// 返回值 null时报错
optional2.ifPresent(a -> System.out.println(a));//a为空时不处理
System.out.println(optional2.orElse("bbb")); // null时打印bbb,否则为本身
System.out.println(optional2.orElseGet(() -> "hello"));//null时调用Supplier.get
Student student = new Student();
student.setBooks(Arrays.asList(new Book()));
Optional<Student> optionalStudent = Optional.of(student);
System.out.println(optionalStudent.map(s -> s.getBooks()).orElse(Collections.emptyList()));
//最终版
Optional.ofNullable(student).map(a->a.getBooks()).orElse(Collections.emptyList());
}
Method reference
1. 方法引用实际上是Lambda表达式的一种语法糖
a->System.out.println(a); == System.out::println;
2. 方法引用分类:
1. 类名::静态方法名 参数和返回值和函数一样
2. 引用名::实例方法名
3. 类名::实例方法名
4. 构造方法引用: 类名::new
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person implements Comparable<Person> {
private String name;
private Integer age;
@Override
public int compareTo(Person person) {
return this.getAge() - person.getAge();
}
public static int sortAscByAge(Person beforePerson,Person afterPerson){
return beforePerson.getAge()-afterPerson.getAge();
}
private int sortDescByAge(Person beforePerson,Person afterPerson){
return afterPerson.getAge()-beforePerson.getAge();
}
public Person getPerson(Supplier<Person> supplier){
return supplier.get();
}
public String getPerson2(Function<String,String> function){
return function.apply("aaa");
}
public static void main(String[] args) {
List<Person> list = Arrays.asList(new Person("zs",10),
new Person("ls",20),
new Person("ww",15));
//类名::静态方法名
list.sort(Person::sortAscByAge);
//引用名::实例方法名
Person person = new Person();
list.sort(person::sortDescByAge);
//类名::实例方法名
list.sort(Person::compareTo);
System.out.println(list);
//构造方法引用
System.out.println(person.getPerson(Person::new));
System.out.println(person.getPerson2(String::new));
}
}
Stream
1. 流有3部分组成
1. 源
2. 零个或多个中间操作
3. 终止操作
2. 流操作类型
1. 惰性求值(无终止操作时,中间操作不进行)
2. 及早求值
流一旦关闭或使用过,再次使用会报异常。
流的创建方式
public static void main(String[] args) {
// 可变参数
Stream<String> stream = Stream.of("a","b","ab");
String[] strs = {"a", "c"};
// 数组
Stream<String> stream1 = Stream.of(strs);
// Arrays方法
Stream<String> stream2 = Arrays.stream(strs);
// 集合方法
List<String> list = new ArrayList<>();
Stream<String> stream3 = list.stream();
}
example
public class StreamText {
public static final List<Integer> fromUids = Arrays.asList(10031,10044,10045,10046,10055,10069);
public static final List<Integer> toUids = Arrays.asList(10031,10044,10045,10046,10055,10069,1);
public static void main(String[] args) {
List<Transaction> transactionList = Arrays.asList(
new Transaction(10031,10044),
new Transaction(10031,10001),
new Transaction(10044,1)
);
List<Transaction> collect = transactionList.stream().filter(a -> !(fromUids.contains(a.getFromUid()) && toUids.contains(a.getToUid())))
.collect(Collectors.toList());
System.out.println(collect);
}
}
@Data
@AllArgsConstructor
class Transaction{
private Integer fromUid;
private Integer toUid;
}
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4,5,6);
// 集合 *2 求和
Integer sum = list.stream().map(a -> a * 2).reduce(0, Integer::sum);
System.out.println(sum);
// 组合List
List<String> list = Arrays.asList("hi","hello");
List<String> list1 = Arrays.asList("zs","ls","ww");
list.stream().flatMap(item->list1.stream().map(item2 -> item + " " +item2)).forEach(System.out::println);
}
Stream方法
public static void main(String[] args) {
Stream<String> stream = Stream.of("hello","world","aaa");
//转数组
String[] strings = stream.toArray(String[]::new);
//转集合
List<String> collect = stream.collect(Collectors.toList());
//LinkedList
List<String> list = stream.collect(LinkedList::new,LinkedList::add,LinkedList::addAll);
// 可以写多种形式
List<String> linkedList = stream.collect(Collectors.toCollection(LinkedList::new));
Set<String> set = stream.collect(Collectors.toSet());
//拼接 结果:helloworldaaa
String str = stream.collect(Collectors.joining());
//映射 全部转为大写并输出
stream.map(String::toUpperCase).forEach(System.out::println);
//flatMap 将多级集合放入同一级使用
List<List<Integer>> listList = Arrays.asList(Arrays.asList(1),Arrays.asList(2,3,4), Arrays.asList(5,6));
listList.stream().flatMap(item->item.stream()).forEach(System.out::println);
//iterate无限流 需要有终止条件
Stream.iterate(1,a -> a+2).limit(5).reduce(Integer::sum).ifPresent(System.out::println);
//mapToInt mapToLong mapToDouble 避免装箱拆箱的性能损耗
Stream.iterate(1, a -> a + 2).limit(6).filter(a -> a > 2).mapToInt(a -> a * 2).skip(2).limit(2).sum();
//IntSummaryStatistics 可以获取多个值
IntSummaryStatistics intSummaryStatistics = Stream.iterate(1, a -> a + 2).limit(6).filter(a -> a > 2)
.mapToInt(a -> a * 2).skip(2).limit(2).summaryStatistics();
System.out.println(intSummaryStatistics.getSum());
System.out.println(intSummaryStatistics.getAverage());
// distinct 去重 根据equal方法判断
Stream.of("a","a").distinct().forEach(System.out::println);
}
Stream分组
public class StreamGroupBy {
public static void main(String[] args) {
List<Dog> list = Lists.newArrayList(
new Dog("xiaohua",1),
new Dog("xiaohuang",2),
new Dog("xiaohong",3),
new Dog("xiaohua",3)
);
Map<String, List<Dog>> collect = list.stream().collect(Collectors.groupingBy(Dog::getName));
//list没有数据时,返回map为空的map
Map<String, Long> collect1 = list.stream().collect(Collectors.groupingBy(Dog::getName, Collectors.counting()));
//获取平均值 等类似sql
Map<String, Double> collect2 = list.stream().collect(Collectors.groupingBy(Dog::getName, Collectors.averagingDouble(Dog::getAge)));
//分区 结果分为true和false两部分
Map<Boolean, List<Dog>> collect3 = list.stream().collect(Collectors.partitioningBy(dog -> dog.getAge() >= 3));
}
}
@Data
@AllArgsConstructor
class Dog{
private String name;
private Integer age;
}
Collect
1. collect: 收集器
2. Collector是collect方法的参数
3. Collector是一个接口,是一个可变的汇聚操作,将输入元素累积到一个可变的容器中,在所有元素处理完成后,将结果转为一个最终的表示,
支持串行和并行两种执行方式。
4. Collectors是一个提供很多Collector实现的工具类
example
public static void main(String[] args) {
list.stream().collect(Collectors.minBy(Comparator.comparingInt(Dog::getAge))).ifPresent(System.out::println);
List<String> list = Arrays.asList("nihao","hello","world","hello world");
//cccnihao,hello,world,hello worldaaa
System.out.println(list.stream().collect(Collectors.joining(",","ccc","aaa")));
list.sort(Comparator.comparingInt(String::length).thenComparing(Comparable::compareTo).reversed());
}
日期
1. jdk8之前使用Date、Calendar、SimpleDateFormat,有线程安全和使用不方便的缺点
2. jdk8之前可以封装DateUtils或者使用JodaTime
JodaTime
1. 引入joda-time jar包
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<!--spring-boot项目有对应版本-->
</dependency>
example
public static void main(String[] args) {
DateTime dateTime = new DateTime();
DateTime tomorrow = dateTime.plusDays(1);
System.out.println(dateTime.toString("yyyy-MM-dd HH:mm:ss"));
System.out.println(tomorrow.toString("yyyy-MM-dd HH:mm:ss"));
System.out.println(dateTime.withDayOfMonth(1).toString("yyyy-MM-dd HH:mm:ss"));
LocalDate localDate = new LocalDate();
// 三个月前的最后一天
System.out.println(localDate.minusMonths(3).dayOfMonth().withMaximumValue());
// 两年前的三月
System.out.println(localDate.minusYears(2).monthOfYear().setCopy(3));
}
java.time.*
public static void main(String[] args) {
//当前时间 yyyy-MM-dd
LocalDate localDate = LocalDate.now();
// 2019-10-1
LocalDate localDate1 = LocalDate.of(2019, 10, 1);
// 2019,10,1
System.out.println(localDate1.getYear()+","+localDate1.getMonthValue()+","+localDate1.getDayOfMonth());
MonthDay monthDay = MonthDay.now();
MonthDay monthDay1 = MonthDay.from(localDate);
// true monthDay比较月和天(生日)
System.out.println(monthDay.equals(monthDay1));
// HH:mm:ss.SSS
LocalTime localTime = LocalTime.now();
// +2小时-20分钟
System.out.println(localTime.plusHours(2).minusMinutes(20));
//增加一个星期 俩种写法
System.out.println(localDate.plusWeeks(1));
System.out.println(localDate.plus(1, ChronoUnit.WEEKS));
//日期比较
boolean b = localDate.isAfter(localDate1);
boolean b1 = localDate.isBefore(localDate1);
System.out.println(localDate.isEqual(LocalDate.now()));
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime.equals(new Date()));
//获得两个日期相隔年月日
Period period = Period.between(localDate, localDate1);
System.out.println(period.getYears());
System.out.println(period.getMonths());
System.out.println(period.getDays());
//获取两个时间天数间隔
LocalDate now = LocalDate.now();
LocalDate newYear = LocalDate.of(2020,1,25);
System.out.println(newYear.toEpochDay()-now.toEpochDay());
}