1.学习lambda表达式 函数式编程
1.1 DEMO1
public class DMEO1 {public static void main(String[] args) {Runnable runnable = new Runnable() {@Overridepublic void run() {System.out.println("子线程执行");}};new Thread(runnable).start();//lambda表达式runnable = () -> System.out.println("子线程执行2");new Thread(runnable).start();new Thread(() -> System.out.println("子线程执行3")).start();//比较器//匿名内部类写法Comparator com = new Comparator() {@Overridepublic int compare(String o1, String o2) {return o1.length() - o2.length();}};//lambda表达式Comparator com2 = (String o1, String o2) -> {return o1.length() - o2.length();};//形参类型自动推断Comparator com3 = (o1, o2) -> o1.length() - o2.length();Comparator com4 = Comparator.comparingInt(String::length);//匿名内部类会生成class文件,lambda不会生成class文件}
}
1.2 DEMO2 Usb
- 函数行接口入门
- @FunctionalInterface //声明这是一个函数式接口
public class DEMO2 {public static void main(String[] args) {//匿名内部类Usb mouse = new Usb() {@Overridepublic void service() {System.out.println("鼠标开始运动");}};mouse.service();//lanbda表达式Usb fan = () -> System.out.println("风扇开始运行。。。。");run(mouse);run(fan);}private static void run(Usb usb) {usb.service();}}
@FunctionalInterface //声明这是一个函数式接口
public interface Usb {void service();
}
1.3 DEMO3
public class DEMO3 {public static void main(String[] args) {//使用lambda表达式happy(t -> System.out.println("聚餐消费了:" + t), 100);happy(t -> System.out.println("唱歌消费了:" + t), 200);int[] arr = getNums(() -> new Random().nextInt(100), 5);System.out.println(Arrays.toString(arr));//如果lambda表达式方法体中只是调用一个特定的已经存在的方法,则可以使用方法引用//常见形式有 对象::实例方法 类::静态方法 类::实例方法 类::newString abe = handlerString(s -> s.toUpperCase(), "abe");String abe1 = handlerString(String::toUpperCase, "abe"); //简写;方法引用String abe2 = handlerString(s -> s.trim(), " zhangsan ");String abe3 = handlerString(String::trim, " zhangsan ");System.out.println("abe = " + abe);System.out.println("abe1 = " + abe1);System.out.println("abe2 = " + abe2);System.out.println("abe3 = " + abe3);List names = new ArrayList<>();names.add("zhangsan1");names.add("lisi");names.add("wangwu");names.add("zhangsan2");List list = filterNames((s) -> s.startsWith("zhangsan"), names);System.out.println(list.toString());List list2 = filterNames((s) -> s.length() > 4, names);System.out.println(list2.toString());}//Consumer 消费型接口public static void happy(Consumer consumer, double money) {consumer.accept(money);}//Supplier 供给型接口public static int[] getNums(Supplier supplier, int count) {int[] arr = new int[count];for (int i = 0; i < count; i++) {arr[i] = supplier.get();}return arr;}//Function 函数型接口public static String handlerString(Function function, String str) {return function.apply(str);}//Predicate 断言型接口public static List filterNames(Predicate predicate, List list) {List resultList = new ArrayList<>();for (String string : list) {if (predicate.test(string)) {resultList.add(string);}}return resultList;}
}
1.4 DEMO4
- 如果lambda表达式方法体中只是调用一个特定的已经存在的方法,则可以使用方法引用
- 常见形式有
- 对象::实例方法
- 类::静态方法
- 类::实例方法
- 类::new
//如果lambda表达式方法体中只是调用一个特定的已经存在的方法,则可以使用方法引用
//常见形式有 对象::实例方法 类::静态方法 类::实例方法 类::new
public class DEMO4 {public static void main(String[] args) {//1.对象::实例方法Consumer consumer = s -> System.out.println(s);Consumer consumer1 = System.out::println;consumer.accept("hello");consumer1.accept("hello");//2.类::静态方法Comparator com = (o1, o2) -> Integer.compare(o1, o2);Comparator com1 = Integer::compare;int compare = com.compare(10, 9);int compare1 = com1.compare(10, 9);System.out.println("compare = " + compare);System.out.println("compare1 = " + compare1);//3.类::实例方法Function function = e -> e.getName();Function function1 = Employee::getName;String name = function.apply(new Employee("zhangsan", "100"));String name1 = function1.apply(new Employee("lisi", "100"));System.out.println("name = " + name);System.out.println("name1 = " + name1);//4.类::newSupplier supplier = () -> new Employee();Supplier supplier1 = Employee::new;}
}
public class Employee {private String name;private String money;public Employee(String name, String money) {this.name = name;this.money = money;}public Employee() {}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getMoney() {return money;}public void setMoney(String money) {this.money = money;}@Overridepublic String toString() {return "Employee{" +"name='" + name + '\'' +", money='" + money + '\'' +'}';}
}
2.学习stream
- Stream 自己不会存储元素
- Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream
- Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行
2.1使用stream
创建:创建一个流
- 通过Collection对象的stream()或者parallelStream()方法;parallelStream是并行流
- 通过Arrays类的stream()方法
- 通过stream接口的of()、iterate()、generate()方法
- 通过IntStream、LongStream、DoubleStream接口中的of()、range()、rangeClosed()方法
public class Demo1 {public static void main(String[] args) {// 1.通过Collection对象的stream()或者parallelStream()方法;parallelStream是并行流ArrayList arrayList = new ArrayList<>();arrayList.add("zhangsan");arrayList.add("lisi");arrayList.add("zhaowu");Stream stream = arrayList.stream();//遍历// stream.forEach(s-> System.out.println(s));stream.forEach(System.out::println);//并行流Stream stream1 = arrayList.parallelStream();stream1.forEach(System.out::println);// 2.通过Arrays工具类的stream()方法String[] arr = {"aaa", "bbb", "ccc"};Stream stream2 = Arrays.stream(arr);stream2.forEach(System.out::println);// 3.通过stream接口的of()、iterate()、generate()方法Stream stream3 = Stream.of(10, 20, 30, 40);stream3.forEach(System.out::println);//迭代流Stream iterate = Stream.iterate(0, x -> x + 2);iterate.limit(10).forEach(System.out::println);//生成流Stream generate = Stream.generate(() -> new Random().nextInt(100));generate.limit(10).forEach(System.out::println);// 4.通过IntStream、LongStream、DoubleStream接口中的of()、range()、rangeClosed()方法IntStream intStream = IntStream.of(100, 200, 300);intStream.forEach(System.out::println);IntStream.range(0,50).forEach(System.out::println); //0-49IntStream.rangeClosed(0,50).forEach(System.out::println);//0-50}
}
中间操作:在一个或多个步骤中,将初始stream转换到另一个stream的中间操作
- filter 过滤
- limit 限制
- skip 跳过
- distinct 去重
- sorted 排序
- map 映射为map
- parallel 获取并行流
public class DEMO2 {public static void main(String[] args) {ArrayList list = new ArrayList<>();list.add(new Employee("小王",15000));list.add(new Employee("小张",12000));list.add(new Employee("小李",18000));list.add(new Employee("小孙",17000));list.add(new Employee("小刘",15000));list.add(new Employee("小刘",15000));//中间操作System.out.println("-------1. filter 过滤-----------");// 1. filter 过滤list.stream().filter(e->e.getMoney()>15000).forEach(System.out::println);System.out.println("-------2. limit 限制-----------");// 2. limit 限制list.stream().limit(2).forEach(System.out::println);System.out.println("-------3. skip 跳过-----------");// 3. skip 跳过list.stream().skip(2).forEach(System.out::println);System.out.println("-------4. distinct 去重-----------");// 4. distinct 去重list.stream().distinct().forEach(System.out::println); //去重的依据是重写hashcode和equalSystem.out.println("-------5. sorted 排序-----------");// 5. sorted 排序list.stream().sorted(Comparator.comparingDouble(Employee::getMoney)).forEach(System.out::println);System.out.println("-------6. map 映射为map-----------");// 6. map 映射为maplist.stream().map(Employee::getName).forEach(System.out::println);System.out.println("-------7. parallel 获取并行流-----------");// 7. parallel 获取并行流 采用多线程,效率相对高list.parallelStream().forEach(System.out::println);/*** 演示串行流和并行流的区别*/ArrayList list1 = new ArrayList<>();for (int i = 0; i < 500000; i++) {list1.add(UUID.randomUUID().toString());}//串行long start = System.currentTimeMillis();long count = list1.stream().sorted().count();System.out.println("count = " + count);long end = System.currentTimeMillis();System.out.println("用时:"+(end-start));//并行long start1 = System.currentTimeMillis();long count1 = list1.parallelStream().sorted().count();System.out.println("count1 = " + count1);long end1 = System.currentTimeMillis();System.out.println("用时:"+(end1-start1));}
}
终止操作:使用一个终止操作来产生一个结果。该操作会强制它之前的延迟操作立即执行。在这之后,该stream就不能使用了。
- forEach
- min
- max
- count
- reduce
- collect 收集
public class DEMO3 {public static void main(String[] args) {ArrayList list = new ArrayList<>();list.add(new Employee("小王", 15000));list.add(new Employee("小张", 12000));list.add(new Employee("小李", 18000));list.add(new Employee("小孙", 17000));list.add(new Employee("小刘", 15000));list.add(new Employee("小刘", 15000));//终止操作list.stream().filter(e -> {System.out.println("执行过滤了。。。");return e.getMoney() > 15000;}) //中间操作延迟执行.forEach(System.out::println);System.out.println("---------------min---------------------");//Optional防止空指针Optional min = list.stream().min(Comparator.comparingDouble(Employee::getMoney));System.out.println(min.get());System.out.println("---------------count---------------------");long count = list.stream().count();System.out.println(count);System.out.println("---------------reduce---------------------");//reduce 规约//计算所有员工的工资和Optional reduce = list.stream().map(Employee::getMoney).reduce((x, y) -> x + y);System.out.println(reduce.get());System.out.println("---------------collect---------------------");//collect//获取员工信息后,封装成一个list集合List collect = list.stream().map(Employee::getName).collect(Collectors.toList());collect.forEach(System.out::println);}
}
public class DEMO1 {public static void main(String[] args) {List userInfoList = new ArrayList<>();userInfoList.add(new UserInfo(1L, "捡田螺的小男孩", 18));userInfoList.add(new UserInfo(2L, "程序员田螺", 27));userInfoList.add(new UserInfo(2L, "捡瓶子的小男孩", 26));System.out.println("===================1.list转map=========================");/*** list 转 map* 使用Collectors.toMap的时候,如果有可以重复会报错,所以需要加(k1, k2) -> k1* (k1, k2) -> k1 表示,如果有重复的key,则保留第一个,舍弃第二个*/Map userInfoMap = userInfoList.stream().collect(Collectors.toMap(UserInfo::getId, userInfo -> userInfo, (k1, k2) -> k1));userInfoMap.values().forEach(a-> System.out.println(a.getName()));System.out.println("===================2.groupingBy分组=========================");List originUserInfoList = new ArrayList<>();originUserInfoList.add(new UserInfo(1L, "捡田螺的小男孩", 18,"深圳"));originUserInfoList.add(new UserInfo(3L, "捡瓶子的小男孩", 26,"湛江"));originUserInfoList.add(new UserInfo(2L, "程序员田螺", 27,"深圳"));//提到分组,相信大家都会想起SQL的group by。我们经常需要一个List做分组操作。比如,按城市分组用户。在Java8之前,是这么实现的:HashMap> result = new HashMap<>();for (UserInfo userInfo : originUserInfoList) {String city = userInfo.getCity();List userInfos = result.get(city);if (userInfos == null) {userInfos = new ArrayList<>();result.put(city, userInfos);}userInfos.add(userInfo);}//而使用Java8的groupingBy分组器,清爽无比:Map> collect = originUserInfoList.stream().collect(Collectors.groupingBy(UserInfo::getCity));}
}
3.新时间API
3.1 之前的时间API存在问题:线程安全问题、设计混乱
3.2 本地化日期时间API
- LocalDate 日期
- LocalTime 时间
- LocalDateTime 日期时间
//LocalDateTime的使用
public class DEMO3 {public static void main(String[] args) {LocalDateTime localDateTime = LocalDateTime.now();
// LocalDateTime localDateTime2 = LocalDateTime.of(year,month,dayofMonth,hour,minute);System.out.println("localDateTime = " + localDateTime);System.out.println("localDateTime.getYear() = " + localDateTime.getYear());System.out.println("localDateTime.getMonthValue() = " + localDateTime.getMonthValue());System.out.println("localDateTime.getDayOfMonth() = " + localDateTime.getDayOfMonth());//添加2天LocalDateTime plusDays = localDateTime.plusDays(2);System.out.println("plusDays = " + plusDays);//减少一个月LocalDateTime minusMonths = localDateTime.minusMonths(1);System.out.println("minusMonths = " + minusMonths);}
}
3.3 Instant 时间戳
3.4 ZoneId 时区
3.5 Date 、Instant 、LocalDateTime的转换
//Instant 时间戳
//ZoneId 时区
public class DEMO4 {public static void main(String[] args) {//Instant 时间戳Instant instant = Instant.now();System.out.println("now = " + instant); //与当时间差8个小时System.out.println("+=================================");System.out.println(instant.toEpochMilli()); //当前时间戳System.out.println(System.currentTimeMillis());System.out.println("+=================================");//添加10秒钟Instant instant1 = instant.plusSeconds(10);//相差时间System.out.println(Duration.between(instant,instant1).toMillis());System.out.println("+=================================");//ZoneId 时区Set availableZoneIds = ZoneId.getAvailableZoneIds();for (String availableZoneId : availableZoneIds) {System.out.println(availableZoneId);}System.out.println("+=================================");System.out.println(ZoneId.systemDefault().toString());System.out.println("+=================================");// Date =>Instant=>LocalDateTimeDate date = new Date();Instant instant2 = date.toInstant();System.out.println("instant2 = " + instant2);LocalDateTime localDateTime = LocalDateTime.ofInstant(instant2, ZoneId.systemDefault());System.out.println("localDateTime = " + localDateTime);//LocalDateTime =>Instant=>DateSystem.out.println("+=================================");Instant instant3 = localDateTime.atZone(ZoneId.systemDefault()).toInstant();System.out.println("instant3 = " + instant3);Date from = Date.from(instant3);System.out.println("from = " + from);}
}
3.6 DateTimeFormatter 格式化类
//DateTimeFormatter 格式化类
public class DEMO5 {public static void main(String[] args) {DateTimeFormatter dft = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");//把时间格式化成字符串String format = dft.format(LocalDateTime.now());System.out.println("format = " + format);System.out.println("+============================");//把字符串解析为时间LocalDateTime localDateTime = LocalDateTime.parse("2022-11-27 14:27:24", dft);System.out.println("localDateTime = " + localDateTime);}
}