一句话总结一下Java8,“以前需要几行、十几行、几十行的代码,现在只需一行,统统只需一行。”
Java8改进的主要有lambda表达式、stream流处理、optional类、日期类型、优化集合api和并发api
1. Lambda表达式
先看个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public List<Apple> filterRedApples(List<Apple> apples) { List<Apple> result = new ArrayList<>(); for (Apple apple : apples) { if ("red".equals(apple.getColor())) { result.add(apple); } } return result; } public List<Apple> filterRedApples(List<Apple> apples) { List<Apple> result = new ArrayList<>(); for (Apple apple : apples) { if (apple.getWeight() > 10) { result.add(apple); } } return result; }
|
这两个方法只有 if 语句不同,其他的完全相同,有很大的冗余性。如果能把 if 语句里面的内容当成参数传递,就可以整合成一个方法了。
Java8之前方法只能传递对象或者集合,现在Java8可以通过方法传递行为(或者叫函数)。
1 2 3 4
| 新建个接口和方法,用来抽象化 if 语句 public interface Predicate<T> { boolean test(T t); }
|
1 2 3 4 5 6 7 8 9 10
| 把接口传入方法 List<Apple> filterApples(List<Apple> apples, Predicate<Apple> predicate) { List<Apple> result = new ArrayList<>(); for (Apple apple : apples) { if (predicate.test(apple)) { result.add(apple); } } return result; }
|
1 2 3 4 5 6 7 8
| filterApples(apples, apple -> "red".equals(apple.getColor())); filterApples(apples, apple -> apple.getWeight() > 10); filterApples(apples, apple -> "red".equals(apple.getColor()) && apple.getWeight() > 10);
|
很强大吧!Java8内置常用的lambda函数接口,平时开发完全不用亲自去写函数接口。
2. Stream流处理
Java8针对集合新增了Stream流API,每次操作需要把集合先转换成流,可以理解为把集合放在流水线上,层层加工,最后再转换成想要的结果。
流API中可以传递lambda函数,算是强大的lambda函数的一个实践。
1 2
| List<Apple> redApples = apples.stream().filter(apple -> "red".equals(apple.getColor())).collect(Collectors.toList());
|
通俗易懂,先把集合转换成流,然后筛选颜色是红色的,最后再转换成List集合,一行代码解决。
1 2 3 4 5 6 7 8 9 10 11
| List<String> appleNames = apples.stream().map(apple -> apple.getName()).collect(Collectors.toList()); List<String> appleNames = apples.stream().map(Apple::getName).collect(Collectors.toList()); List<Apple> orderedApples = apples.stream() .sorted(Comparator.comparing(Apple::getWeight).reversed()).collect(Collectors.toList()); Map<String, List<Apple>> groupedApples = apples.stream().collect(Collectors.groupingBy(Apple::getColor));
|
流可以操作集合像写SQL语句一样容易,流还有很多方法,比如:find、match、reduce、distinct、skip、limit、count、sum、max、min等,满足你的各种复杂的需求。
3. optional类
先看个例子:
1 2 3 4 5 6 7 8 9 10 11 12
| public String getCarInsuranceName(Person person) { if (person != null) { Car car = person.getCar(); if (car != null) { Insurance insurance = car.getInsurance(); if (insurance != null) { return insurance.getName(); } } } }
|
即使代码素养很高的你也常常写出这样令人崩溃的代码吧,层层判空,深度质疑,现在有了Java8,可以做出一些改变了。
1 2 3 4 5
| public String getCarInsuranceName(Optional<Insurance> insurance) { Optional<String> name = insurance.map(Insurance::getName); return name.orElse("Unknown"); }
|
Optional提供了map方法,如果insurance为空,就不去调用getName方法,然后给返回值设置默认值。
1 2 3 4 5 6 7
| public String getCarInsuranceName(Optional<Person> person) { return person.map(Person::getCar) .map(Car::getInsurance) .map(Insurance::getName) .orElse("Unknown"); }
|
4. 日期类型
旧的日期类型,例如Date、Calendar、DateFormat都存在诸多问题,以至于每家公司都要复写大量日期函数的方法,或者引入第三方的日期时间库,例如Joda-Time。
现在Java8引入了LocalDate、LocalTime、Instant、Duration、Period,让你轻松需求。
看几个常用的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| LocalDate nowDate = LocalDate.now(); LocalDateTime nowDateTime = LocalDateTime.now(); int year = nowDate.getYear(); LocalDate localDate = nowDateTime.toLocalDate(); LocalDate firstDayOfMonth = nowDate.with(TemporalAdjusters.firstDayOfMonth()); LocalDate parse = LocalDate.parse("2017-07-11"); String format = nowDateTime .format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM));
|
Java8的日期函数非常强大,什么复杂的需求都能轻松实现。
5. 优化集合api
List、Map集合新增很多实用的api,看几个常用的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| apples.forEach(System.out::println); groupedApples.forEach((k, v) -> System.out.println(k + "," + v)); apples.forEach(apple -> { apple.setColor("red"); System.out.println(apple); }); List<Integer> numbers = Arrays.asList(2, 3, 5); numbers.replaceAll(number -> number * 2); System.out.println(numbers); List<String> cars = new ArrayList<>(); cars.add("Aston Martin"); cars.removeIf(car -> "Aston Martin".equals(car)); Map<String, Integer> carInventory = new HashMap<>(); Integer count = 0; if (carInventory.containsKey("Aston Martin")) { count = carInventory.get("Aston Martin"); } Integer count = carInventory.getOrDefault("Aston Martin", 0); public String getData(String url) { String data = cache.get(url); if (data == null) { data = getData(url); cache.put(url, data); } return data; } public String getData(String url) { return cache.computeIfAbsent(url, this::getData); } String[] arr = {"aa", "bb", "cc","dd"}; System.out.println(String.join(",", arr));
|
6. 优化并发api
stream流有parallel方法,可用作并行处理。
也优化了其他并发api。