一、并行数据处理与性能
-
并行流
-
通过对收集源调用parallelStream方法来把集合转换为并行流。并行流就是一个把内容分成多个数据块,并用不同的线程分别处理每个数据块的流。
// 返回从1到给定参数n的所有数字之和 // 顺序流 public static long sequentialSum(long n) { return Stream.iterate(1L, i -> i + 1) // 生成自然数无限流 .limit(n) // 限制到前n个数 .reduce(0L, Long::sum); // 对所有数字求和来归纳流 } // 并行流 public static long sequentialSum(long n) { return Stream.iterate(1L, i -> i + 1) .limit(n) .parallel() // 将流转换为并行流 .reduce(0L, Long::sum); }
-
对顺序流调用parallel方法并不意味着流本身有任何实际的变化,对并行流调用sequential方法就可以把它变成顺序流。也可以把这两个方法结合起来,可以更细化地控制在遍历流时哪些操作要并行执行,哪些要顺序执行
stream.parallel() .filter(...) .sequential() .map(...) parallel() .reduce();
-
二、用Optional取代null
-
Optional类:变量存在时,Optional类只是对类简单封装。变量不存在时,缺失的值会被建模成一个“空” 的Optional对象,由方法Optional.empty()返回。Optional.empty()方法是一个静态工厂方法,它返回Optional类的特定单一实例。
// 人可能有车,也可能没有车,使用Optional可以避免空指针异常 public class Person { private Optional<Car> car; public Optional<Car> getCar() { return car; } } public class Car { private Optional<Insurance> insurance; public Optional<Insurance> getInsurance() { return insurance; } } public class Insurance { private String name; // 保险公司必须有名字 public String getName() { return name; } }
-
应用Optional 的几种模式
-
声明空的Optional
Optional<Person> optPerson = Optional.empty();
-
依据一个非空值创建Optional
// 如果person是一个null,这段代码会立即抛出一个NullPointerException Optional<Person> optPerson = Optional.of(person);
-
可接受null的Optional
// 使用静态工厂方法Optional.ofNullable,你可以创建一个允许null值的Optional对象,如果person是null,那么得到的Optional对象就是个空对象。 Optional<Person> optPerson = Optional.ofNullable(person);
-
使用map从Optional对象中提取和转换值
Optional<Insurance> optInsurance = Optional.ofNullable(insurance); Optional<String> name = optInsurance.map(Insurance::getName)
-
使用flatMap链接Optional 对象
// 使用Optional获取car的Insurance名称 public String getCarInsuranceName(Optional<Person> person) { return person.flatMap(Person::getCar) .flatMap(Car::getInsurance) .map(Insurance::getName) .orElse("unknown"); }
-
默认行为及解引用Optional对象
① get():如果变量存在,它直接返回封装的变量 值,否则就抛出一个NoSuchElementException异常。
② orElse((T other):允许在Optional对象不包含值时提供一个默认值。
③ orElseGet(Supplier<? extends T> other):是orElse方法的延迟调用版,Supplier 方法只有在Optional对象不含值时才执行调用。
④ orElseThrow(Supplier<? extends X> exceptionSupplier):在Optional对象为空时都会抛出一个异常,但是使用orElseThrow你可以定制希 望抛出的异常类型。
⑤ ifPresent(Consumer):在变量值存在时执行一个作为参数传入的 方法,否则就不进行任何操作。
-
使用filter剔除特定的值:filter方法接受一个谓词作为参数。如果Optional对象的值存在,并且它符合谓词的条件, filter方法就返回其值;否则它就返回一个空的Optional对象
// 检查保险公司的名称是否为“Cambridge-Insurance” Optional<Insurance> optInsurance = ...; optInsurance.filter(insurance -> "CambridgeInsurance".equals(insurance.getName())) .ifPresent(x -> System.out.println("ok"));
-
-
Optional类的方法总结
三、新的日期和时间API
-
LocalDate:该类的实例是一个不可变对象,它只提供了简单的日期,并不含当天的时间信息。另外,它也不附带任何与时区相关的信息。
// 创建一个LocalDate对象并读取其值 LocalDate date = LocalDate.of(2014, 3, 18); int year = date.getYear(); Month month = date.getMonth(); int day = date.getDayOfMonth(); DayOfWeek dow = date.getDayOfWeek(); // 当前月的天数 int len = date.lengthOfMonth(); // 是否是闰年 boolean leap = date.siLeapYear(); // 获取当前日期 LocalDate today = LocalDate.now();
-
LocalTime
LocalTime time = LocalTime.of(13, 45, 20); int hour = time.getHour(); int minute = time.getMinute(); int second = time.getSecond(); // 获取当前时间 LocalTime now = LocalTime.now()
-
LocalDateTime
// 2014-03-18T13:45:20 LocalDateTime dt1 = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45, 20); LocalDateTime dt2 = LocalDateTime.of(date, time); LocalDateTime dt3 = date.atTime(13, 45, 20); LocalDateTime dt4 = date.atTime(time); LocalDateTime dt5 = time.atDate(date); // 从LocalDateTime中提取LocalDate或者LocalTime LocalDate date1 = dt1.toLocalDate(); LocalTime time1 = dt1.toLocalTime(); // 获取当前日期和时间 LocalDateTime now = LocalDateTime.now();
-
DateTimeFormatter:以一定的格式创建代表特定日期或时间的字符串,和老的java.util.DateFormat相比较,所有的DateTimeFormatter实例都是线程安全 的。
// 两个不同的格式器生成了字符串 LocalDate date = LocalDate.of(2014, 3, 18); String s1 = date.format(DateTimeFormatter.BASIC_ISO_DATE); // 20140318 String s2 = date.format(DateTimeFormatter.ISO_LOCAL_DATE); // 2014-03-18 // 通过解析代表日期或时间的字符串重新创建该日期对象 LocalDate date1 = LocalDate.parse("20140318", DateTimeFormatter.BASIC_ISO_DATE); LocalDate date2 = LocalDate.parse("2014-03-18", DateTimeFormatter.ISO_LOCAL_DATE); // 按照某个模式创建DateTimeFormatter DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yy"); LocalDate date1 = LocalDate.of(formatter); String formattedDate = date1.format(formatter); LocalDate date2 = LocalDate.parse(formattedDate, formatter); // 创建一个本地化的DateTimeFormatter DateTimeFormatter italianFormatter = DateTimeFormatter.ofPattern("d. MMMM yyyy", Locale.ITALIAN); LocalDate date1 = LocalDate.of(2014, 3, 18); String formattedDate = date.format(italianFormatter); // 18. marzo 2014 LocalDate date2 = LocalDate.parse(formattedDate, italianFormatter); // DateTimeFormatterBuilder类构造更加复杂的格式器 DateTimeFormatter italianFormatter = new DateTimeFormatterBuilder() .appendText(ChronoField.DAY_OF_MONTH) .appendLiteral(". ") .appendText(ChronoField.MONTH_OF_YEAR) .appendLiteral(" ") .appendText(ChronoField.YEAR) .parseCaseInsensitive() .toFormatter(Locale.ITALIAN);
-