java steam reduce_Java 8新特性:Stream API与Date API

除此之外,Java8 API中包含了很多内建的函数式接口,这些接口都增加了@FunctionalInterface注解以便能用在lambda表达式上。它还提供了很多全新的函数式接口来让工作更加方便,其中有很多是来自我们熟悉的第三方类库Guava。

Steam API

Stream API是Java8类库的核心,它能够应用在一组元素上一次执行的操作序列。

Stream操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,这样你我们就可以将多个操作串起来。

使用Stream的时候需要指定一个数据源,它包括List, Set等集合类。

Filter操作

Stream接口支持很多操作,Filter操作就是最常用的操作之一。在工程中,我们经常需要对一个集合进行过滤。以之前的排序数据为例:List words = new ArrayList<>();

words.add(new SomeObject("test5"));

words.add(new SomeObject("some0"));

words.add(new SomeObject("another3"));

words.add(new SomeObject("test1"));

words.add(new SomeObject("some9"));

words.add(new SomeObject("another2"));

我们需要过滤掉test的数据:words.stream().filter((SomeObject someObject) -> !someObject.getSomething().startsWith("test")).forEach(System.out::println);

我们使用stream API中的filter函数,它使用了Predicate接口,它的抽象方法返回值是boolean。filter函数根据它的返回值判断该元素是否被过滤掉。forEach方法表示将每个过滤后的每个元素依次执行指定操作。forEach方法使用的是Consumer接口,它的抽象方法表示在单个参数上执行的参数。

Sort操作

Stream同样支持排序,我们可以指定Comparator函数式接口来让其按照自定义的方式进行排序:final int plus = 1;

words.stream().sorted((o1, o2) -> (o1.getSomething() + plus).compareTo(o2.getSomething())).forEach(System.out::println);

简单的一句话后排序就完成了,我们可以在之后进行后续操作或迭代输出。这个操作并不会影响原始数据,而是生成一个新的流供我们使用。

匹配

Stream支持多种匹配策略,这个操作会返回boolean告知我们匹配结果。// 测试是否含有前缀为test的元素

words.stream().anyMatch((s)->s.getSomething().startsWith("test"));

// 测试是否每个元素前缀均为test

words.stream().allMatch((s)->s.getSomething().startsWith("test"));

// 测试是否没有后缀为1的元素

words.stream().noneMatch((s)->s.getSomething().endsWith("1"));

映射

中间操作map会将元素根据指定的Function接口来依次将元素转成另外的对象,下面的示例展示了将字符串转换为大写字符串。你也可以通过map来讲对象转换成其他类型,map返回的Stream类型是根据你map传递进去的函数的返回值决定的。比如我们需要将SomeObject数组的每个元素的something字段都变为大写。words.stream().map(s -> s.getSomething().toUpperCase()).forEach(System.out::println);

计数和Reduce

除了按次序输出,我们也可以使用其他的最终操作。

计数是其中一个常见的操作,我们经常需要统计筛选出元素的个数,通过流接口,我们可以很轻松的完成:words.stream().filter((SomeObject someObject) -> !someObject.getSomething().startsWith("test")).count();

Reduce也是一个很有意思的操作,它允许通过指定的函数来讲stream中的多个元素合并为一个元素,结果是通过Optional接口表示,words.stream().filter((SomeObject someObject) -> !someObject.getSomething().startsWith("test")).reduce((o1, o2)->new SomeObject(o1.getSomething().concat(o2.getSomething())));

并行Stream

默认情况下Stream是在一个线程执行的。为了提高性能,我们也可以使用并行Stream。比如之前的filter操作,我们只要将其调用的stream方法改为parallelStream即可:words.parallelStream().filter((SomeObject someObject) -> !someObject.getSomething().startsWith("test")).reduce((o1, o2)->new SomeObject(o1.getSomething().concat(o2.getSomething())));

Date API

Java8在java.time包中包含了一组全新的时间日期API。新的日期API和开源的Joda-Time库差不多,但也有一些不同。我们来通过一些例子来学习下如何使用新的Date API吧。

Clock

Clock类提供了访问当前日期和时间的方法,Clock是时区敏感的,可以用来取代 System.currentTimeMillis() 来获取当前的微秒数。某一个特定的时间点也可以使用Instant类来表示,Instant类也可以用来创建老的java.util.Date对象。Clock clock = Clock.systemDefaultZone();

long millis = clock.millis();

Instant instant = clock.instant();

Date legacyDate = Date.from(instant);

Timezones 时区

在新API中时区使用ZoneId来表示。时区可以很方便的使用静态方法of来获取到。 时区定义了到UTS时间的时间差,在Instant时间点对象到本地日期对象之间转换的时候是极其重要的。ZoneId zone1 = ZoneId.of("Europe/Berlin");

ZoneId zone2 = ZoneId.of("Brazil/East");

System.out.println(zone1.getRules());

System.out.println(zone2.getRules());

本地时间LocalTime

LocalTime 定义了一个没有时区信息的时间,例如晚上7点。下面的例子使用前面代码创建的时区创建了两个本地时间。之后比较时间并以小时和分钟为单位计算两个时间的时间差:LocalTime now1 = LocalTime.now(zone1);

LocalTime now2 = LocalTime.now(zone2);

System.out.println(now1.isBefore(now2)); // false

long hoursBetween = ChronoUnit.HOURS.between(now1, now2);

long minutesBetween = ChronoUnit.MINUTES.between(now1, now2);

本地日期LocalDate

LocalDate 表示了一个确切的日期,比如 2015-04-10。该对象值是不可变的,用起来和LocalTime基本一致。下面的例子展示了如何给Date对象加减天/月/年。另外要注意的是这些对象是不可变的,操作返回的总是一个新实例。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();

LocalDateTime 本地日期时间

LocalDateTime 同时表示了时间和日期,相当于前两节内容合并到一个对象上了。LocalDateTime和LocalTime还有LocalDate一样,都是不可变的。LocalDateTime提供了一些能访问具体字段的方法。LocalDateTime time = LocalDateTime.of(2015, Month.April, 10, 4, 10, 1);

DayOfWeek dayOfWeek = time.getDayOfWeek();

附加上时区信息,就可以将其转换为一个时间点Instant对象,Instant时间点对象可以很容易的转换为老式的java.util.Date:Instant instant = sylvester

.atZone(ZoneId.systemDefault())

.toInstant();

Date legacyDate = Date.from(instant);

Map

虽然Map不支持Stream API来进行操作。但是新的类库中,Map类提供了一些函数式编程的方法。比如我们需要遍历输出所有value:map.forEach((key, value)->System.out.println(value));

或是合并操作:map.merge("existKey", "newValue", (value, newValue)->value.concat(newValue));

merge方法可以将内容插入到Map中,如果这个key已存在就执行Lambda表达式所指定的操作进行合并,否则直接进行插入操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值