jdk8新特性
来源:互联网 发布:淘宝网站首页源代码 编辑:程序博客网 时间:2024/05/20 21:21
jdk8最大特性便是在于提供了函数式接口和Lambda表达式。Functional Interface(函数式接口,简称FI), 即只包含唯一一个抽象方法的接口, 称为FI 。 而 Lambada表达式是基于函数式接口之上的。不多说了,我们直接上代码,看一下jdk8特性的使用:
package jdk8;import java.time.Clock;import java.time.DayOfWeek;import java.time.Instant;import java.time.LocalDate;import java.time.LocalDateTime;import java.time.LocalTime;import java.time.Month;import java.time.ZoneId;import java.time.format.DateTimeFormatter;import java.time.format.FormatStyle;import java.time.temporal.ChronoField;import java.time.temporal.ChronoUnit;import java.util.Arrays;import java.util.Collections;import java.util.Comparator;import java.util.Date;import java.util.HashMap;import java.util.List;import java.util.Locale;import java.util.Map;import java.util.Optional;import java.util.concurrent.Executors;import java.util.concurrent.ThreadLocalRandom;import java.util.function.Consumer;import java.util.function.Function;import java.util.function.Predicate;import java.util.function.Supplier;/* * jdk7 引入了 ForkJoinPool * divide and conquer : 分而治之 算法 * ForkJoinPool 有如下特点: * 1:work stealing, 当一个任务划分一个新线程时,它将自己推到 deque 的头部. * 当一个任务执行与另一个未完成任务的合并操作时,它会将另一个任务推到队列头部并执行 * 当线程的任务队列为空,它将尝试从另一个线程的 deque 的尾部 窃取另一个任务 * 2:避免等待子问题线程返回 * * ThreadPoolExecutor 和 ForkJoinPool都继承了AbstractExecutorService, * ForkjoinPool使用到了RecursiveAction和RecursiveTask,他们分别表示不需要执行结果和需要返回执行结果的场景。 * 而ThreadPoolExecutor使用Runnable和Callable的参数来分别表示不需要返回值和需要返回值的线程执行对象 *//** * jdk8 特性 * * Java编译器的新特性 * 一、方法参数名称, javac -parameter进行编译,使用Parameter.getName()方法可以取得方法名字, 该属性默认是关闭的。 * 二、Nashorn JavaScript引擎, 使得我们可以在JVM上开发和运行JS应用, 使用jjs运行js文件,如:jjs func.js。例子如下: * ScriptEngineManager manager = new ScriptEngineManager(); * ScriptEngine engine = manager.getEngineByName( "JavaScript" ); * System.out.println( engine.getClass().getName() ); * System.out.println( "Result:" + engine.eval( "function f() { return 1; }; f() + 1;" ) ); * 三、 类依赖分析器:jdeps, 它可以展示包层级和类层级的Java类依赖关系,它以.class文件、目录或者Jar文件为输入,然后会把依赖关系输出到控制台。 * 四、使用Metaspace(JEP 122)代替持久代(PermGen space)。 * 在JVM参数方面,使用-XX:MetaSpaceSize和-XX:MaxMetaspaceSize代替原来的-XX:PermSize和-XX:MaxPermSize。 */public class Features { public static void main(String[] args) { MR(); } /* * 特性一:接口的默认方法和静态方法,即接口添加非抽象的方法实现,只需要使用 default关键字即可 * defalue修饰的方法是不被Lambda表达式访问的 */ interface Formula{ double calculate(int a); default double sqrt(int a) { return Math.sqrt(a); } } /* * 特性二:Lambda 表达式, 任何可以接受一个FI实例的地方,都可以用Lambda表达式 * lambda: 可以直接访问标记了final的外层局部变量,或者实例的字段以及静态变量 */ public static void Lambda(){ List<String> names = Arrays.asList("peter", "anna", "mike", "xenia"); // 老写法 Collections.sort(names, new Comparator<String>() { @Override public int compare(String a, String b) { return b.compareTo(a); } }); // jdk1.8 的Lambda 写法 Collections.sort(names, (String a, String b) -> { return b.compareTo(a); }); // 对于函数体只有一行代码的,你可以去掉大括号{}以及return关键字 Collections.sort(names, (String a, String b) -> b.compareTo(a)); // Java编译器可以自动推导出参数类型,所以你可以不用再写一次类型 Collections.sort(names, (a, b) -> b.compareTo(a)); // 上面几种写法,等价下面这种写法 names.sort((a, b) -> b.compareTo(a)); // 如果表达式不需要参数呢?好吧,那也必须有圆括号 Executors.newSingleThreadExecutor().execute(() -> {/* Runnable do something. */}); } /* * 特性三:Functional Interface(函数式接口,以下简称FI), 即只包含唯一一个抽象方法的接口, 称为FI * 使用 @FunctionalInterface注解, 如 Runnable、 Comparator、Predicate、Function、Supplier、Consumer、Filter都是FI */ @FunctionalInterface interface FI { public abstract void run(); } /* * 特性四:Method References(方法引用, 简称MR), Lambda表达式的代码只有一个简单的方法调用的时候,可以简化为MR * 即使用 :: 关键字来传递方法或者构造函数引用, * MR分为四种: 静态方法\某个特定对象的实例方法\某个类的实例方法\构造函数 */ public static void MR(){ List<String> ints = Arrays.asList("peter", "anna", "mike", "xenia"); // 一、引用 静态方法, 注意:这个方法接受一个特定类型的参数。 ints.sort(String::compareTo); // 升序 // 二、引用 某个特定对象的实例方法, 注意:这个方法接受一个特定类型的参数。 ints.forEach(System.out::println); // 三、引用 某个特定对象的实例方法,注意:这个方法没有定义入参数 ints.stream().map(String::length); // 四、引用类的 构造函数, 注意:这个构造器没有参数。 ints.stream().map(StringBuilder::new); } // 特性五:Predicate 接口只有一个参数,返回boolean类型 public static void testPredicate(){ /* * lambda 声明一个Predicate接口的实现类,实现了Predicate 接口的 test() * 等价于 * Predicate<String> predicate = new Predicate<String>(){ * boolean test(String s){ * return s.length() > 0; * } * } */ Predicate<String> predicate = (s) -> s.length() > 0; predicate.test("foo"); predicate.negate().test("foo"); // 使用方法引用时, 引用的方法返回值必须是 boolean类型且无参 @SuppressWarnings("unused") Predicate<String> predicate1 = String::isEmpty; } // 特性六:Function 接口一个参数并且返回一个结果,并附带了一些可以和其他函数组合的默认方法(compose, andThen): public static void testFunction(){ /* * Function<String, Integer> toInteger = Integer::valueOf * 等价于 * Function<String, Integer> predicate = new Predicate<String, Integer>(){ * Integer apply(String s){ * return Integer.valueOf(s); * } * } */ Function<String, Integer> toInteger = Integer::valueOf; Function<String, String> backToString = toInteger.andThen(String::valueOf); backToString.apply("123"); } // 特性七:Supplier 接口返回一个任意范型的值,和Function接口不同的是该接口没有任何参数 public static void testSupplier(){ Supplier<Features> fSupplier = Features::new; fSupplier.get(); // 返回Features实例对象 } // 特性八:Consumer 接口表示执行在单个参数上的操作 public static void testConsumer(){ Consumer<Features> greeter = (p) -> System.out.println("Hello, "); greeter.accept(new Features()); // 返回Features实例对象 } // 特性九:Comparator java中的经典接口, Java 8在此之上添加了多种默认方法 public static void testComparator(){ @SuppressWarnings("unused") Comparator<String> comparator = (p1, p2) -> p1.compareTo(p2); } /* * 特性十:Optional 不是函数是接口,这是个用来防止NullPointerException异常的辅助类型 * Optional 被定义为一个简单的容器,其值可能是null或者不是null * 在Java 8中,不推荐你返回null而是返回Optional。 */ public static void testOptional(){ Optional<String> optional = Optional.of("bam"); optional.isPresent(); // true optional.get(); // "bam" optional.orElse("fallback"); // "bam" optional.ifPresent((s) -> System.out.println(s.charAt(0))); // "b" } /* * 特性十一:Stream 不是函数式接口,表示能应用在一组元素上一次执行的操作序列。 * Stream 操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,这样你就可以将多个操作依次串起来。 * Stream 的创建需要指定一个数据源,比如 java.util.Collection的子类,List或者Set, Map不支持 * Stream 仅仅代表着数据流,并没有数据结构,所以他遍历完一次之后便再也无法遍历 */ public static void testStream(){ List<String> ints = Arrays.asList("peter", "anna", "mike", "xenia"); // 一:Filter 过滤,中间操作, 通过 Predicate 接口来过滤并只保留符合条件的元素。 ints.stream().filter((s) -> s.startsWith("a")).forEach(System.out::println); /* * 二:Sort 排序,中间操作,通过 Comparator 接口返回的是排序好后的Stream。如果不指定自定义的Comparator则会使用默认排序。 * sorted只是创建一个流对象排序的视图,而不会改变原来集合中元素的顺序 */ ints.stream().sorted().forEach(System.out::println); // 三:Map 映射, 中间操作, 通过 Function 接口将元素根据指定的Function接口来依次将元素转成另外的对象。 ints.stream().map(String::toUpperCase).forEach(System.out::println); // 转大写 // 四:Match 匹配, 最终操作, 通过检测指定的 Predicate 是否匹配整个Stream ints.stream().allMatch((s) -> s.startsWith("a")); // 所有满足以a开头,则返回ture ints.stream().anyMatch((s) -> s.startsWith("a")); // 只要存在一个满足以a开头,则返回ture ints.stream().noneMatch((s) -> s.startsWith("a")); // 不存在以a开头,则返回ture // 五:Count 计数, 最终操作,返回Stream中元素的个数,返回值类型是long。 ints.stream().filter((s) -> s.startsWith("a")).count(); // 六:Reduce 规约 计数, 最终操作,通过 Optional 将stream中的多个元素规约为一个元素。 ints.stream().reduce((s1, s2) -> s1 + "#" + s2); // 七:forEach是一个最终操作。通过 Consumer 接口进行遍历操作 ints.stream().forEach(System.out::println); /* * 八:并行和串行Stream。串行Stream上的操作是在一个线程中依次完成,而并行Stream则是在多个线程上同时执行。 * 100 000 次遍历, 并行Stream快了50%之多 */ ints.stream().sorted().count(); ints.parallelStream().sorted().count(); } /* * 特性十二: Map类型不支持stream,不过Map提供了一些新的有用的方法来处理一些日常任务。 */ public static void testMapFetures(){ Map<Integer, String> map = new HashMap<>(); for (int i = 0; i < 10; i++) { // 如果map中有对应K映射的V且不为null则直接返回;否则执行put map.putIfAbsent(i, "val" + i); } // compute重映射, ifPresent会判断key对应的v是否是null,不w为null才会compute->否则直接返回null map.computeIfPresent(3, (num, val) -> val + num); map.get(3); // val33 map.computeIfPresent(9, (num, val) -> null); map.containsKey(9); // false map.computeIfAbsent(23, num -> "val" + num); map.containsKey(23); // true map.computeIfAbsent(3, num -> "bam"); map.get(3); // val33 // Map里删除一个键值全都匹配的项: map.remove(3, "val3"); map.get(3); // val33 map.remove(3, "val33"); map.get(3); // null // 不存在或为空,返回默认值 map.getOrDefault(42, "not found"); // Merge做的事情是如果键名不存在则插入,否则则对原键对应的值做合并操作并重新插入到map中 map.merge(9, "val9", (value, newValue) -> value.concat(newValue)); map.get(9); // val9 map.merge(9, "concat", (value, newValue) -> value.concat(newValue)); map.get(9); // val9concat } /* * 特性十三: Date API NEW FETURES */ @SuppressWarnings("unused") public static void testDateApiFutures(){ // 一、Clock类提供了访问当前日期和时间的方法,Clock是时区敏感的,可以用来取代 System.currentTimeMillis() 来获取当前的微秒数。 Clock clock = Clock.systemDefaultZone(); long millis = clock.millis(); Instant instant = clock.instant(); Date legacyDate = Date.from(instant); // legacy java.util.Date /* * 二、Timezones 时区, 在新API中时区使用ZoneId来表示。 * 时区可以很方便的使用静态方法of来获取到。 时区定义了到UTS时间的时间差,在Instant时间点对象到本地日期对象之间转换的时候是极其重要的。 */ System.out.println(ZoneId.getAvailableZoneIds()); // prints all available timezone ids ZoneId zone1 = ZoneId.of("Europe/Berlin"); ZoneId zone2 = ZoneId.of("Brazil/East"); System.out.println(zone1.getRules()); System.out.println(zone2.getRules()); /* * 三、LocalTime 本地时间, 定义了一个没有时区信息的时间。 * 提供了多种工厂方法来简化对象的创建,包括解析时间字符串。 */ LocalTime now1 = LocalTime.now(zone1); LocalTime now2 = LocalTime.now(zone2); System.out.println(now1.isBefore(now2)); // false System.out.println(ChronoUnit.HOURS.between(now1, now2)); // 两个时间相差几小时 -3 System.out.println(ChronoUnit.MINUTES.between(now1, now2)); // 两个时间相差几分钟 -239 LocalTime late = LocalTime.of(23, 59, 59); System.out.println(late); // 23:59:59 DateTimeFormatter germanFormatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT).withLocale(Locale.GERMAN); LocalTime leetTime = LocalTime.parse("13:37", germanFormatter); System.out.println(leetTime); // 13:37 /* * 三、LocalDate 本地日期, 表示了一个确切的日期,比如 2014-03-11。该对象值是不可变的. */ LocalDate today = LocalDate.now(); LocalDate tomorrow = today.plus(1, ChronoUnit.DAYS); LocalDate yesterday = tomorrow.minusDays(2); LocalDate independenceDay = LocalDate.of(2014, Month.JULY, 4); DayOfWeek dayOfWeek = independenceDay.getDayOfWeek(); germanFormatter = DateTimeFormatter .ofLocalizedDate(FormatStyle.MEDIUM).withLocale(Locale.GERMAN); LocalDate xmas = LocalDate.parse("24.12.2014", germanFormatter); System.out.println(xmas); // 2014-12-24 /* * 四、LocalDateTime 本地日期时间, LocalDateTime和LocalTime还有LocalDate一样,都是不可变的。 */ LocalDateTime sylvester = LocalDateTime.of(2014, Month.DECEMBER, 31, 23, 59, 59); dayOfWeek = sylvester.getDayOfWeek(); System.out.println(dayOfWeek); // WEDNESDAY Month month = sylvester.getMonth(); System.out.println(month); // DECEMBER long minuteOfDay = sylvester.getLong(ChronoField.MINUTE_OF_DAY); System.out.println(minuteOfDay); // 1439 // 只要附加上时区信息,就可以将其转换为一个时间点Instant对象,Instant时间点对象可以很容易的转换为老式的java.util.Date instant = sylvester .atZone(ZoneId.systemDefault()).toInstant(); legacyDate = Date.from(instant); System.out.println(legacyDate); // Wed Dec 31 23:59:59 CET 2014 } /* * 特性十四: 多重注解 */ //@Path //@Path public static void testRepeatAnnotation(){ } /* * 特性十五: 并行数组 * 使用parallelSetAll()方法生成20000个随机数,然后使用parallelSort()方法进行排序。 * 这个程序会输出乱序数组和排序数组的前10个元素。 */ public static void testParalleArrays(){ long[] arrayOfLong = new long [ 20000 ]; Arrays.parallelSetAll( arrayOfLong, index -> ThreadLocalRandom.current().nextInt( 1000000 ) ); Arrays.stream( arrayOfLong ).limit( 10 ).forEach( i -> System.out.print( i + " " ) ); System.out.println(); Arrays.parallelSort( arrayOfLong ); Arrays.stream( arrayOfLong ).limit( 10 ).forEach( i -> System.out.print( i + " " ) ); System.out.println(); }}
0 0
- jdk8新特性
- JDK7、JDK8新特性
- JDK8新特性
- JDK8新特性-Lambda
- JDK8新特性-Stream
- JDK8新特性
- JDK8新特性
- jdk8新特性
- JDK8新特性--Stream
- JDK8新特性
- jdk8 新特性
- JDK8新特性介绍
- jdk8新特性
- jdk8新特性
- jdk8新特性之流
- JDK8新特性一览
- jdk8新特性
- JDK8新特性
- 个位数与个位数的积
- Eclipse使用技巧 - 5. Eclipse代码自动补全失效解决办法
- vim的基本配置
- UICollectionViewFlowLayout备忘录
- 获取上周时间
- jdk8新特性
- Android 消息机制 以及Message、Handler、Message Queue、Looper之间的关系。
- vb
- 问题:willDisplayHeaderView在 iOS7下不被调用
- 乐观锁和悲观锁
- Android Studio多渠道签名打包
- iOS导入cocos2d游戏
- Linux系统下通过nginx运行WordPress
- js中top、clientTop、scrollTop、offsetTop的区别 文字详细说明版