java8新特性

1.lambda表达式

          Lambda 允许把函数作为参数传递进方法中

          // 类型声明 MathOperation addition = (int a, int b) -> a + b; 

          // 不用类型声明 MathOperation subtraction = (a, b) -> a - b;

          // 大括号中的返回语句 MathOperation multiplication = (int a, int b) -> { return a * b; };

          Lambda 表达式只能引用标记了 final 的外层局部变量,lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改

    2.方法引用

        构造器引用:它的语法是Class::new,或者更一般的Class< T >::new

        public static Car create(final Supplier<Car> supplier) { return supplier.get(); }

        final Car car = Car.create( Car::new );

        静态方法引用:它的语法是Class::static_method

        public static void collide(final Car car) { System.out.println("Collided " + car.toString()); }

        cars.forEach( Car::collide );

        特定类的任意对象的方法引用:它的语法是Class::method

        public void repair() { System.out.println("Repaired " + this.toString()); }

        cars.forEach( Car::repair );

      特定对象的方法引用:它的语法是instance::method

      public void follow(final Car another) { System.out.println("Following the " + another.toString()); }

      final Car police = Car.create( Car::new );

      cars.forEach( police::follow );

    3.Stream

        Stream(流)是一个来自数据源的元素队列并支持聚合操作

        数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。

        聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。

        forEach    limit    sorted 

        Random random = new Random();

        random.ints().limit(10).sorted().forEach(System.out::println);

        map

        List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);

        // 获取对应的平方数

        List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());

        filter

        List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");

        // 获取空字符串的数量

        long count = strings.stream().filter(string -> string.isEmpty()).count();

        Collectors

        List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");

        List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());

        System.out.println("筛选列表: " + filtered);

        String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));

        System.out.println("合并字符串: " + mergedString);

(1)Stream创建

1) 通过参数序列创建Stream

// 利用可变参数直接构造Stream,相比Arrays.stream()更简单

// 下面语句创建的流内容:10,20,30,40,50

final IntStream stream = IntStream.of(10, 20, 30, 40, 50);

// 下面语句创建的流内容:red,blue,green

final Stream<String> colorStream = Stream.of("red", "blue", "green");

2) 通过数组创建Stream

相比Stream.of(),不用区分基础数据类型,但参数只能是数组,不支持参数序列创建

final Integer[] numbers = {10, 20, 30, 40, 50, 60};

final Stream<Integer> numberStream = Arrays.stream(numbers);

final int[] intNumbers = {10, 20, 30, 40, 50, 60};

final IntStream result = Arrays.stream(intNumbers);

3) 通过集合创建Stream

final Collection<Integer> collection = Lists.newArrayList(10, 20, 30, 40, 50, 60);

final Stream<Integer> numberStream = collection.stream();

4) 通过集合创建并行Stream

final Collection<Integer> numbers = Lists.newArrayList(10, 20, 30, 40, 50, 60);

// 直接创建并行流

Stream<Integer> numberStream = numbers.parallelStream();

// 将串行流转换为并行流

numberStream = numbers.stream().parallel();

5) 通过IO方式创建Stream

// 读取文件的内容,生成stream流

final Stream<String> stream = Files.lines(Paths.get("data.txt"), Charsets.UTF_8);

// 获取目录下的文件列表信息

final Stream<Path> listFile = Files.list(Paths.get("/"));

6) 通过生成器创建Stream

SecureRandom random = SecureRandom.getInstanceStrong();

// 直接传入instance::method

// 下面语句创建的result包含10个随机数

Stream<Integer> result = Stream.generate(random::nextInt).limit(10);

// 直接传入lambda表达式

// 下面语句创建的result包含10个元素,每个值由根据当前时间 % 100计算得来

// 以某次执行为例,result包含36,3,40,71,46,43,68,97,38,92

result = Stream.generate(() -> (int) (System.nanoTime() % 100)).limit(10);

7) 通过iterate创建Stream

// 以0为种子,f(n) = n + 3, f(f(n)) ...

// 下面语句创建的Stream内容:0 3 6 9 12 15 18 21 24 27

Stream.iterate(0, n -> n + 3).limit(10).forEach(Stubs::doWhatever);

8) 通过区间创建整数序列Stream

// 通过range、rangeClosed生成序列,该序列为数学中的区间序列。

// 生成[-100, 100)区间的元素序列,不包括end元素100

final IntStream range = IntStream.range(-100, 100);

// 由于start > end,不符合区间定义,返回空区间,Stream中元素长度为0

final IntStream emptyRange = IntStream.range(100, -100);

// 生成[-100,100]区间的元素序列,包含end元素100

final IntStream rangeClosed = IntStream.rangeClosed(-100, 100);

// LongStream range生成

// 生成[-100, 100)区间的元素序列,不包括end元素100

final LongStream longRange = LongStream.range(-100L, 100L);

// 生成[-100,100]区间的元素序列,包含end元素100

final LongStream longRangeClosed = LongStream.rangeClosed(-100L, 100L);

(1)Stream基础操作

1) 计算Stream大小

// 计算Stream中元素的格式,count为特殊的reduce操作,对于sum(), max(), min(), average(),count()等操作不建议直接使用reduce()

// 等同于stream.mapToLong(e -> 1L).sum();

long count = Stream.of().count(); // count = 0

count = Stream.of(10).count(); // count = 1

count = Stream.of(10, 20, 30, 40, 50).count(); // count = 5

1) Stream转换为字符串

final Stream<String> stream = Stream.of("red", "blue", "green");

// 执行结果:colors值为red|blue|green

String colors = stream.collect(Collectors.joining("|"));

2) Stream转换为数组

final Stream<String> stream = Stream.of("red", "blue", "green");

// 执行结果:colors数组为[red, blue, green]

String[] colors = stream.toArray(String[]::new);

3) Stream转换为ArrayList

final Stream<String> stream = Stream.of("red", "blue", "green");

// colors类型为ArrayList,结果为[red, blue, green]

List<String> colors = stream.collect(Collectors.toList());

4) Stream转换为List

不同业务场景对性能、内存占用等有不同的诉求。对于ArrayList不满足的场景,可将Stream元素收集到指定类型的List,如:LinkedList。

final Stream<String> stream = Stream.of("red", "blue", "green");

// Stream转换的List类型为LinkedList

// 执行结果:colors结果为[red, blue, green]

List<String> colors = stream.collect(Collectors.toCollection(LinkedList::new));

5) Stream转换为指定类型Collection

final Stream<String> stream = Stream.of("red", "blue", "green");

// colors为LinkedHashSet,对于其他的类型在toCollection()方法参数中指定

Set<String> colors = stream.collect(Collectors.toCollection(LinkedHashSet::new));

6) Stream转换为Set

final Stream<String> stream = Stream.of("red", "blue", "green");

// 默认转换为HashSet

// 执行结果:colors值为[red, green, blue]

final Set<String> colors = stream.collect(Collectors.toSet());

7) Stream转换为Map

Collectors.toMap()需要保证Key唯一性,如果不唯一,则需给出合并策略

Collectors.toMap()需要保证Stream元素为NonNull,且映射到Map的value值必须为NonNull

final Stream<User> stream = Stream.of(new User("1", "Jerry", "Male"), new User("2", "Kitty", "Female"));

// 以User的ID作为key,User实例作为value,转换过程默认使用的是HashMap

// user.getId()必须是唯一的,否则会抛出java.lang.IllegalStateException: Duplicate key

// 执行结果:map值为

// {1=User(id=1, username=Jerry, salary=0, gender=Male), 2=User(id=2, username=Kitty, salary=0, gender=Female)}

Map<String, User> map = stream.collect(Collectors.toMap(User::getId, Function.identity()));

final Stream<User> stream2 = Stream.of(new User("1", "Jerry", "Male"), new User("2", "Kitty", "Female"));

// 将User的ID作为key,username作为value

// 执行结果:mapIdName值为{1=Jerry, 2=Kitty}

Map<String, String> mapIdName = stream2.collect(Collectors.toMap(User::getId, User::getUsername));

如果Collectors.toMap() key值不唯一,给出合并策略

final Stream<User> duplicateKeyStream =

    Stream.of(new User("1", "Jerry", "Male"), new User("20", "Jerry", "Female"));

// 下面以username作为key,Stream中存在同名的username "Jerry"。

// 以“后者覆盖前者”的策略解决冲突

// 执行结果:map值为{Jerry=User(id=20, username=Jerry, salary=0, gender=Female)}

Map<String, User> map =

    duplicateKeyStream.collect(Collectors.toMap(User::getUsername, Function.identity(), (key1, key2) -> key2));

如果Stream存在null元素,Collectors.toMap()转换失败,建议通过filter()过滤后再进行转换

final Stream<User> nullElementStream = Stream.of(new User("1", "Jerry", "Male"), null);

// 下面代码Stream中存在null元素,Collectors.toMap()将抛出NullPointerException异常

Map<String, String> mapIdName = nullElementStream.collect(Collectors.toMap(User::getId, User::getUsername));

// 过滤出NonNull的元素后进行Map转换,转换后的结果为{1=Jerry}

nullElementStream.filter(Objects::nonNull).collect(Collectors.toMap(User::getId, User::getUsername));

如果Map的value值为null,Collectors.toMap()转换失败,建议通过filter()过滤后再进行转换

final Stream<User> nullValueStream = Stream.of(new User("1", "Jerry", "Male"), new User("2", null));

// 将id、username信息转换为map,由于存在username为null,Collectors.toMap()将抛出NullPointerException异常

Map<String, String> mapIdName = nullValueStream.collect(Collectors.toMap(User::getId, User::getUsername));

// 过滤出Map的value为NonNull的元素后进行Map转换,转换后的结果为{1=Jerry}

nullValueStream.filter(p -> p != null && StringUtils.isNotEmpty(p.getUsername()))

    .collect(Collectors.toMap(User::getId, User::getUsername));

8) Stream转换为分组Map

final Stream<User> stream = Stream.of(new User("1", "Jerry", "Male"), new User("2", "Kitty", "Female"));

// 按性别分组,分组结果为

// {Female=[User(id=2, username=Kitty, salary=0, gender=Female)], Male=[User(id=1, username=Jerry, salary=0,

// gender=Male)]}

Map<String, List<User>> group = stream.collect(Collectors.groupingBy(User::getGender));

// Stream实例执行一次终端操作后将不能再次使用,因此,此处创建新的Stream

final Stream<User> stream2 = Stream.of(new User("1", "Jerry", "Male"), new User("2", "Kitty", "Female"));

// 按是否为Female分组,分组结果为

// {false=[User(id=1, username=Jerry, salary=0, gender=Male)], true=[User(id=2, username=Kitty, salary=0,

// gender=Female)]}

Map<Boolean, List<User>> group2 =

    stream2.collect(Collectors.partitioningBy(p -> "Female".equalsIgnoreCase(p.getGender())));

    4.日期时间 API

        java.time包涵盖了所有处理日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)的操作

        import java.time.LocalDate;

        import java.time.LocalTime;

        import java.time.LocalDateTime;

        import java.time.Month;

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容

  • Java 8自Java 5(发行于2004)以来最具革命性的版本。Java 8 为Java语言、编译器、类库、开发...
    huoyl0410阅读 629评论 1 2
  • Java 8自Java 5(发行于2004)以来最具革命性的版本。Java 8 为Java语言、编译器、类库、开发...
    谁在烽烟彼岸阅读 888评论 0 4
  • 目录结构 介绍 Java语言的新特性2.1 Lambdas表达式与Functional接口2.2 接口的默认与静态...
    夜风月圆阅读 473评论 0 2
  • Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便...
    写代码的杰西阅读 495评论 0 0
  • 一.函数式接口 函数式接口,就是一个接口里面只有一个接口,接口上都用@FunctionalInterface注释修...
    豪大大大阅读 382评论 0 0