JDK8 新特性总结
一、lambda表达式
1.语法
(parameter)->{表达式;} 或
(parameter)->{处理语句;}
2.含义
lambda表达式要看成是一个函数(方法),有方法的(入参 )和 {方法体}组成
3.lambda表达式会对应的一个函数接口的某个方法。
例如:
List.foreach(e->{e.getAge})
lambda表达式e->{e.getAge}对应的函数接口的方法是Consumer<E>接口的accept(E e)方法, 所谓:万变不离其宗,只要记住这个宗,任他怎么变,也不会难道自己
4.对类方法的引用的lambda表达式
语法:
类名::类的方法名
例如:
E::getAge 等同于 (e)->{e.getAge()}
第一种方法引用是构造方法引用,语法是:Class::new ,对于泛型来说语法是:Class<T >::new,请注意构造方法没有参数:
final Car car = Car.create( Car::new );
final List< Car > cars = Arrays.asList( car );
第二种方法引用是静态方法引用,语法是:Class::static_method请注意这个静态方法只支持一个类型为Car的参数。
cars.forEach( Car::collide );
第三种方法引用是类实例的方法引用,语法是:Class::method请注意方法没有参数。
cars.forEach( Car::repair );
最后一种方法引用是引用特殊类的方法,语法是:instance::method,请注意只接受Car类型的一个参数。
final Car police = Car.create( Car::new );
cars.forEach( police::follow );
二、函数接口
1.什么是函数接口
函数接口是一种只有一个方法的接口, 像这样的函数接口可以隐式的转换成lambda表达式
缺点:如果有人在此接口多添加任何一个接口,就会导致编译失败
补救:JDK8提供了一个@FunctionInterface的注解表明函数接口的目的, 记住:接口的默认方法和静态方法不违反函数接口的约定(或定义)
科普-> 匿名内部类:没有类名,且只使用一次,必须继承一个类或实现一个接口 。例如:new Runnable() { public void run(){}} 就是匿名内部类,没有类名实现了Runable接口中的方法。
Runnable r = new Runnable() {
public void run() {
System.out.print(i + " ");
}
};
2.如何定义函数接口
在接口名上加上注解@FunctionInterface, 且接口中只有一个方法(除了:默认方法 和 静态方法),如果有多个方法此类会有错误提示在注解@FunctionInterface上。
三、接口的默认方法和静态方法
1、默认方法
JDK8新概念之一:在接口中新增默认方法,新增的默认的方法必须要有实现,空实现也可以。此默认方法可以被实现类继承,实现类也可以重新默认方法。一个接口可以定义多个default 方法
2.静态方法
JDK8新概念之一:在接口中新增静态方法,新增的静态的方法必须要有实现,空实现也可以。此静态方法只能被此静态方法所在的接口调用,接口的子类都不可以调用此静态方法。一个接口可以定义多个static方法
四、注解
1.重复注解
jdk8之前同一个注解在同一个地方不能超过一次
现在jdk8允许重复注解,但是 定义这个注解的时候需要加@Repeatable (这个注解的数组注解定义类)注解
package com.javacodegeeks.java8.repeatable.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public class RepeatingAnnotations {
@Target( ElementType.TYPE )
@Retention( RetentionPolicy.RUNTIME )
public @interface Filters {
Filter[] value();
}
@Target( ElementType.TYPE )
@Retention( RetentionPolicy.RUNTIME )
@Repeatable( Filters.class )
public @interface Filter {
String value();
};
@Filter( "filter1" )
@Filter( "filter2" )
public interface Filterable {
}
public static void main(String[] args) {
for( Filter filter: Filterable.class.getAnnotationsByType( Filter.class ) ) {
System.out.println( filter.value() );
}
}
}
2.注解的扩展
JDK8新增了ElementType.TYPE_USE 和 ElementType.TYPE_PARAMETER
ElementType.TYPE_USE 针对类型(也叫类)和类型参数,可以限制哪个类型可以进行注解。能在局部变量、泛型类、父类和接口的实现处使用,甚至能在方法上声明异常的地方使用
ElementType.TYPE_PARAMETER 只针对类型参数TypeParameterClass<@TypeParameterAnnotation T>
ElementType.TYPE_PARAMETER
ElementType.TYPE_PARAMETER(Type parameter declaration) 用来标注类型参数。
@Target(ElementType.TYPE_PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface TypeParameterAnnotation {
}
// 如下是该注解的使用例子
public class TypeParameterClass<@TypeParameterAnnotation T> {
public <@TypeParameterAnnotation U> T foo(T t) {
return null;
}
}
ElementType.TYPE_USE
ElementType.TYPE_USE(Use of a type) 能标注任何类型名称,包括上面这个(ElementType.TYPE_PARAMETER的)例子。
public class TestTypeUse {
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TypeUseAnnotation {
}
public static @TypeUseAnnotation class TypeUseClass<@TypeUseAnnotation T> extends @TypeUseAnnotation Object {
public void foo(@TypeUseAnnotation T t) throws @TypeUseAnnotation Exception {
}
}
// 如下注解的使用都是合法的
@SuppressWarnings({ "rawtypes", "unused", "resource" })
public static void main(String[] args) throws Exception {
TypeUseClass<@TypeUseAnnotation String> typeUseClass = new @TypeUseAnnotation TypeUseClass<>();
typeUseClass.foo("");
List<@TypeUseAnnotation Comparable> list1 = new ArrayList<>();
List<? extends Comparable> list2 = new ArrayList<@TypeUseAnnotation Comparable>();
@TypeUseAnnotation String text = (@TypeUseAnnotation String)new Object();
java.util. @TypeUseAnnotation Scanner console = new java.util.@TypeUseAnnotation Scanner(System.in);
}
}
注意:@TypeUseAnnotation 的位置应该在包名右边,类型左边,以下使用例子是错误的,除非给该注解的 @Target 参数里面加上 ElementType.LOCAL_VARIABLE。
@TypeUseAnnotation java.lang.String text;
3.更强的类型推断
Java 8的编译器能更加智能地推断出参数的类型。
public class Value<T> {
public static<T> T defaultValue() {
return null;
}
public T getOrDefault(T value, T defaultValue) {
return (value != null) ? value : defaultValue;
}
}
final Value<String> value = new Value<>();
value.getOrDefault( "22", Value.defaultValue());
Value.defaultValue() 的类型参数能推断出来,不需要写成 Value.<String>defaultValue()。
五、参数名称
如何把参数迷名称保存在java字节码里,并让这些名字在运行时可用。Java 8 终于把这个需求加入到了Java语言(使用反射API和Parameter.getName() 方法)和字节码里(使用java编译命令javac的–parameters xx.java参数)
package com.javacodegeeks.java8.parameter.names;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class ParameterNames {
public static void main(String[] args) throws Exception {
Method method = ParameterNames.class.getMethod( "main", String[].class );
for( final Parameter parameter: method.getParameters() ) {
System.out.println( "Parameter: " + parameter.getName() );
}
}
}
六、容器:Optional(可选的)
Optional<SomeType> getSomeValue() {
// 返回一个空的Optional类型;
return Optional.empty();
}
Optional<SomeType> getSomeValue() {
SomeType value = ...;
// 使用这个方法,值不可以为空,否则抛exception
return Optional.of(value);
}
Optional<SomeType> getSomeValue() {
SomeType value = ...;
// 使用这个方法,值可以为空,如果为空返回Optional.empty
return Optional.ofNullable(value);
public static void optional(){
Optional<String> ot = Optional.ofNullable(null);
System.out.println(ot.isPresent());
System.out.println(ot.orElse("ss"));
System.out.println(ot.orElseGet(()->"ww"));
System.out.println(ot.isPresent()?ot.get():null);
}
输出
false ss ww null Process finished with exit code 0
具体Optional用法参考:点这里链接Optional的详情
七、日期
参考点击这里
/**
* Date 和 LocalDateTime 转换介质为Instant(某一是时刻/瞬间)
*/
public static void DateToLocalDateTime(){
Date date = new Date();
// 入
Instant instant = date.toInstant();// 将Date对象转换成Instant对象
// 出
Date from = Date.from(instant);// 将Instant对象转换成Date对象
Clock clock = Clock.systemDefaultZone();
Instant instant1 = clock.instant();
Instant now = Instant.now(); //获取当前的时间戳
Instant now1 = Instant.now(clock);
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant1, ZoneId.systemDefault());//将Instant对象转换成LocalDateTime对象
Instant instant2 = localDateTime.toInstant(ZoneOffset.UTC);
// 最常用(入、出)
ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
Instant instant3 = zonedDateTime.toInstant();
Date from1 = Date.from(instant3);
}
/**
* 时差信息的日期和时间
* ZoneOffset类用来表示时区,举例来说印度与GMT或UTC标准时区相差+05:30,可以通过ZoneOffset.of()静态方法来 获取对应的时区。
* 一旦得到了时差就可以通过传入LocalDateTime和ZoneOffset来创建一个OffSetDateTime对象
*/
public static void zoneOffset() {
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
ZoneOffset of = ZoneOffset.of("+05:30");
OffsetDateTime of1 = OffsetDateTime.of(now, of);
System.out.println(of1);
}
/**
* 相差期间
*/
public static void duration(){
LocalDateTime from = LocalDateTime.of(2017, Month.DECEMBER, 20, 0, 0, 0);
LocalDateTime to = LocalDateTime.of(2018, Month.DECEMBER, 20, 0, 0, 0);
Duration between = Duration.between(from, to); //期间
System.out.println(between.toDays()); //相差期间为:365 天
System.out.println(between.toHours());//相差期间为:8760 小时
}
/**
* 区域日期时间 --- 最完整的日期时间,包含时区和相对UTC或格林威治的时差
*/
public static void zonedDateTime() {
ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime now1 = ZonedDateTime.now(Clock.systemUTC());
ZonedDateTime now2 = ZonedDateTime.now(Clock.systemDefaultZone());
ZonedDateTime now3 = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
System.out.println(now); //2017-09-20T09:27:31.203+08:00[Asia/Shanghai]
System.out.println(now1);// 2017-09-20T01:27:31.204Z
System.out.println(now2);//2017-09-20T09:27:31.204+08:00[Asia/Shanghai]
System.out.println(now3);//2017-09-20T09:27:31.204+08:00[Asia/Shanghai]
}
/**
* 日期时间 --- 组合了日期和时间,但不包含时差和时区信息
*/
public static void LocalDateTime() {
LocalDateTime now = LocalDateTime.now();// 获取本土日期时间
LocalDateTime now1 = LocalDateTime.now(Clock.systemUTC());// 世界标准日期时间(美国日期时间)和本土日期时间有时差
LocalDateTime now2 = LocalDateTime.now(Clock.systemDefaultZone());// 获取本土日期时间
System.out.println(now);
System.out.println(now1);
System.out.println(now2);
// 本土日期时间格式化
System.out.println(now.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL))); //2017年9月19日 星期二
System.out.println(now.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG))); //2017年9月19日
System.out.println(now.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM))); //2017-9-19
System.out.println(now.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT))); //17-9-19
//System.out.println(now.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.FULL))); //Time无FULL
System.out.println(now.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.LONG))); //下午06时18分55秒
System.out.println(now.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT))); //下午6:19
System.out.println(now.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM))); //18:18:35
System.out.println(now.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG))); //2017年9月19日 下午06时18分55秒
System.out.println(now.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM))); //2017-9-19 18:18:35
System.out.println(now.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT))); //17-9-19 下午6:19
System.out.println(now.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL,FormatStyle.SHORT))); //日期长,时间短:2017年9月19日 星期二 下午6:24
// 自定义
System.out.println(now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"))); //日期长,时间短:2017年9月19日 星期二 下午6:24
System.out.println(now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss", Locale.getDefault()))); //日期长,时间短:2017年9月19日 星期二 下午6:24
System.out.println(now.format(DateTimeFormatter.BASIC_ISO_DATE)); //20170919
System.out.println(now.format(DateTimeFormatter.ISO_TIME)); //18:58:36.494
System.out.println(now.format(DateTimeFormatter.ISO_DATE)); //2017-09-19
System.out.println(now.format(DateTimeFormatter.ISO_DATE_TIME)); //2017-09-19T18:54:05.264
System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_DATE)); //2017-09-19
System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_TIME)); //18:57:07.175
System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); //2017-09-19T18:57:24.485
LocalDateTime parse = LocalDateTime.parse("2012-10-11", DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"));
System.out.println(parse);
System.out.println(now); //2017-09-19T18:57:24.485
}
/**
* 本地时间
*/
public static void localTime(){
// 获取本地时间实例
LocalTime now = LocalTime.now(); // 也是本土时间
LocalTime now1 = LocalTime.now(Clock.systemUTC()); // 世界标准时间(美国时间)和本土时间有时差
LocalTime now2 = LocalTime.now(Clock.systemDefaultZone());// 获取本土时间
System.out.println(now);
System.out.println(now1);
System.out.println(now2);
// 时间格式化
System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_TIME)); // 格式化时间
// 时间的加减
System.out.println(now.plusHours(1)); // 小时加1
System.out.println(now.plusHours(-1)); // 小时减1
// 时分秒的获取
System.out.println(now.getHour()); // 获取小时
System.out.println(now.getMinute()); // 获取分钟
// 处理指定时间
LocalTime from = LocalTime.of(12, 0, 0);
LocalTime to = LocalTime.of(14, 0, 0);
System.out.println(from.withHour(11));//11:00
System.out.println(from);//12:00
System.out.println(to);//14:00
// 时间的判断
System.out.println(from.equals(to));//false
System.out.println(from.isBefore(to));//true
System.out.println(to.isAfter(from));// true
}
/**
* 本地日期
*/
public static void localDate(){
//日期对像的获取
LocalDate now = LocalDate.now();// 也是本土日期
LocalDate now1 = LocalDate.now(Clock.systemUTC());// 世界标准日期(美国日期)
LocalDate now2 = LocalDate.now(Clock.systemDefaultZone());// 获取本土日期
System.out.println(now);
System.out.println(now1);
System.out.println(now2);
// 日期的格式化
System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_DATE));
// 日期的加减(年月日)
System.out.println(now.plusMonths(1));//月加1
System.out.println(now.plusMonths(-1));//月减1
System.out.println(now.plus(1, ChronoUnit.WEEKS));//now上添加一个星期
// 获取年月日
System.out.println(now.getYear());//年
System.out.println(now.getMonthValue());//月
System.out.println(now.getDayOfMonth());//日
System.out.println(now.getDayOfWeek());//星期几 WEDNESDAY
System.out.println(now.getDayOfYear());//一年中的第几天 263
// 处理指定日期
LocalDate from = LocalDate.of(2017, Month.APRIL, 2);//指定2017-04-02
LocalDate to = LocalDate.of(2017, 8, 2);//2017-08-02
System.out.println(to.withDayOfMonth(9));//2017-08-09
System.out.println(to.withMonth(6));//2017-06-02
System.out.println(from);//2017-04-02
System.out.println(to);//2017-08-02
// 日期的判断 --- 如果比较的日期是字符型的,需要先解析成日期对象再作判断
System.out.println(from.equals(to)); // 输出false
System.out.println(from.isBefore(to)); // true
System.out.println(to.isAfter(from)); // true
System.out.println(to.isEqual(from)); // false
System.out.println(to.isLeapYear()); // 判断LocalDate对象to是否是闰年 false
Period between = Period.between(from, to);//和 duration 进行对比下
System.out.println(between.getMonths());// 计算两个日期之间的天数、周数或月数 计算from和to相差的月数 返回4
System.out.println(between.getDays());// 计算两个日期之间的天数、周数或月数 计算from和to相差的日数 返回0
System.out.println(between.getYears());// 计算两个日期之间的天数、周数或月数 计算from和to相差的年数 返回0
// 日期的月日(MonthDay), 没有年(比如:每年你的生日,圣诞节),每年都重复的日子.还说有年月(YearMonth)
MonthDay nowMothDay = MonthDay.now();
MonthDay nowFrom = MonthDay.from(LocalDate.now());
MonthDay nowTo = MonthDay.of(from.getMonthValue(), from.getDayOfMonth());
if (nowFrom.equals(nowTo)) {// 判断当前月日是否是指定的月日
System.out.println("Today is your birthday");
}
//年月(YearMonth)
YearMonth now3 = YearMonth.now();
System.out.println(now3.lengthOfMonth());// 返回当月的天数 30天
System.out.println(now3.lengthOfYear());// 返回当月的天数 365天
}
/**
* 时钟 和 瞬时实例
*/
public static void clock(){
Clock clock = Clock.systemUTC();// 世界标准时钟
Clock clock2 = Clock.systemDefaultZone();// 获取本土时钟
System.out.println(clock.getZone());//Z
System.out.println(clock.instant());//2017-09-20T01:43:40.557Z
System.out.println(clock.millis());//1505871820578
System.out.println(clock2.getZone());//Asia/Shanghai
System.out.println(clock2.instant());//2017-09-20T01:44:57.503Z
System.out.println(clock2.millis());//1505871897503
Instant instant = clock.instant(); // 获取瞬时 实例
}
八、Stream
点击这里讲解Stream单独篇 这是部分案例 这个例子也不错 groupBy
/**
* Stream 不是集合,不是数据结构不保存数据,它是有关算法和计算的,更新一个高级的iterator
*/
public static void streams() {
/**
* 1.其它数据结构转换为Stream(流生成Stream对象)
*/
List<String> strings = Arrays.asList("a", "b", "c");
Stream<String> stream = strings.stream();
Stream<String> stream1 = Arrays.stream(new String[]{"1", "2"});
Stream<Integer> integerStream = Stream.of(1, 2, 3); // boxing 和 unboxing 会很耗时 使用IntStream更合理
// 数值流的构造
IntStream intStream = IntStream.of(1, 2, 3);
LongStream longStream = LongStream.of(1L, 2L, 3L);
DoubleStream doubleStream = DoubleStream.of(1d, 2d, 3d);
IntStream range = IntStream.range(1, 10); // 输出1-9,不包括10
IntStream range2 = IntStream.rangeClosed(1, 10); // 输出1-10,包括10
range.forEach((System.out::println));// 1-9
range2.forEach((System.out::println));// 1-10
/**
* 2.流转换为其它数据结构(一个 Stream 只可以使用一次)
*/
// Array
String[] strArray1 = stream.toArray(String[]::new);
int[] ints = intStream.toArray();
System.out.println(strArray1.length);//3
System.out.println(ints.length);//3
// Collection
List<String> list1 = stream1.collect(Collectors.toList());
List<Integer> list2 = integerStream.collect(Collectors.toCollection(ArrayList::new));
Set set1 = longStream.boxed().collect(Collectors.toSet());
Stack stack1 = doubleStream.boxed().collect(Collectors.toCollection(Stack::new));
System.out.println(list1);//[1, 2]
System.out.println(list2);//[1, 2, 3]
System.out.println(set1);//[1, 2, 3]
System.out.println(stack1);//[1.0, 2.0, 3.0]
// String
String str = strings.stream().collect(Collectors.joining());
System.out.println(str);// abc
/**
* 3.流中元素的操作 (集合的聚合操作【对Stream的使用就是实现一个 filter-map-reduce 过程,产生一个最终结果】)
*/
/**
* Intermediate (流的中间操作是lazy的,并没有正在开始流的遍历【将转换函数输入集合中】)
*
* 包括的操作:map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
*/
/**
* map,mapToInt, flatMap
*/
Stream.of("a", "b", "c").map(String::toUpperCase).collect(Collectors.toList());//map(1:1映射)作用就是把 input Stream 的每一个元素(这里是string集合的一个元素,或是对象集合的一个对象),映射成 output Stream 的另外一个元素(转换成一个大写的一个对象等)
Stream.of("1", "2", "3").mapToInt(value -> Integer.parseInt(value)*Integer.parseInt(value));// 将输入的对象转换成输出的Int对象
//flatMap将List<List<String>>结合转换成List<String> 将一个上层的List<List<String>>转成底层的List<String>
Stream<Integer> flatMap = Stream.of(Arrays.asList(1), Arrays.asList(2, 3), Arrays.asList(4, 5, 6)).flatMap(integers -> integers.stream());//flatMap(1:N 映射)层级结构扁平化 输入为一个List,输出为Integer集合,一个list元素转换成了多个Integer元素。flatMap 把 input Stream 中的层级结构扁平化,就是将最底层元素抽出来放到一起,最终 output 的新 Stream 里面已经没有 List 了,都是直接的数字。
System.out.println(flatMap.collect(Collectors.toList()));
System.out.println(Stream.of("a", "b", "c").filter(s -> {return s.equals("a");}).findAny());// filter(你想要的数据的条件) 对原始 Stream 进行某项测试,通过测试的元素被留下来生成一个新 Stream
System.out.println(Stream.of("a", "b", "a").distinct().collect(Collectors.toList()));//distinct()去重复 [a, b]
System.out.println(Stream.of("a", "b", "c").sorted(Comparator.reverseOrder()).collect(Collectors.toList()));//sorted()顺序排列 Comparator.reverseOrder()反转顺序
System.out.println(Stream.of("a", "b", "c").sorted(Comparator.comparing(String::toString).reversed()).collect(Collectors.toList()));//sorted()顺序排列 comparatorObj.reversed()反转顺序
System.out.println(Stream.of("a", "b", "c").peek(s -> {s.length();s.toUpperCase();}).collect(Collectors.toList()));//peek()类似foreach()但是他不会消费Stream流foreach会
System.out.println(Stream.of("a", "b", "c").limit(2).collect(Collectors.toList()));//[a, b] 从第一个开始到最多size这里是2的集合
System.out.println(Stream.of("a", "b", "c").skip(1).collect(Collectors.toList()));//skip(开始的索引)包含索引上的值 [b, c]
System.out.println(Stream.of("a", "b", "c").parallel().collect(Collectors.toList()));//parallel()并发stream适合在多线程中使用 , 管道来说,如果其元素是有序的,那么 limit 操作的成本会比较大,因为它的返回对象必须是前 n 个也有一样次序的元素。取而代之的策略是取消元素间的次序,或者不要用 parallel Stream
System.out.println(Stream.of("a", "b", "c").sequential().collect(Collectors.toList()));//sequential()有序
System.out.println(Stream.of("a", "b", "c").unordered().collect(Collectors.toList()));//unordered()无序序
/**
* Terminal (流的最终操作才会真正开始流的遍历,并且会生成一个结果,流被用光,无法再被操作【执行转换函数集合】)
*
* 包括的操作:forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
*
*/
Stream.of("a", "b", "c").parallel().forEach(s -> System.out.println(s));// 并发处理的时候,forEach是无序的[b,c,a] ,非并发是有序的
Stream.of("a", "b", "c").parallel().forEachOrdered(s -> System.out.println(s));// 并发处理的时候,forEachOrdered是有序的[a,b,c] (Collectors.toList()也可以保证顺序,都是通过ForEachOrderedTask实现的) ,非并发是有序的
System.out.println(Stream.of("a", "b", "c").parallel().collect(Collectors.toList()));// [a, b, c]
String[] toArray = Stream.of("a", "b", "c").toArray(String[]::new); // 集合转数组
System.out.println(toArray);
/**
* reduce和reducing(聚合操作)方法
* reduce() 和 collect() 的区别是:
* reduce() 的结果是一个值;例如:String reduce = Stream.of("a", "bb", "c").map(String::toUpperCase).reduce("w", (s, s2) -> s.concat(s2));
* collect() 可以对stream中的元素进行各种处理后,得到stream中元素的值;
*/
System.out.println(Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX_VALUE, Double::min));// 求最小值,minValue = -3.0
System.out.println(Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX_VALUE, (aDouble, aDouble2) -> {return Double.min(aDouble,aDouble2);}));// 求最小值,minValue = -3.0
System.out.println(Stream.of("a", "b", "c").reduce("-a", (s,s2)->{ System.out.println(s+"-"+s2); return s.concat(s2);}));// s2集合中的元素, 第一次为s2=a ,s=-a,第二次:s2=b ,s=为上次参数而返回的结果(s+s2)=-aa 返回结果:-a-a|-aa-b|-aab-c
System.out.println(Stream.of("a", "b", "c").reduce("-a",(a,b)->{return a.concat(b);}));//-aabc; a为上次方法体运算后(a.concat(b))返回的结果(初始化为-a),b为集合中遍历的每个元素,不停的遍历计算
System.out.println(Stream.of("a", "bb", "c").collect(Collectors.reducing("w", String::toUpperCase, (s, s2) -> s.concat(s2)))); //和下面一行一样的意思 wABBC
String reduce = Stream.of("a", "bb", "c").map(String::toUpperCase).reduce("w", (s, s2) -> s.concat(s2));
System.out.println(reduce);//wABBC
/**
* 数字Stream(IntStream,LongStream,DoubleStream)
*/
System.out.println(Stream.of(-1.5, 1.0, -3.0, -2.0).mapToDouble(d->d).min().getAsDouble());// 求最小值,minValue = -3.0 min 和 max 的功能也可以通过对 Stream 元素先排序,再 findFirst 来实现
System.out.println(Stream.of(-1.5, 1.0, -3.0, -2.0).mapToDouble(d->d).max().getAsDouble());// 求最最大值
System.out.println(Stream.of(-1.5, 1.0, -3.0, -2.0).mapToDouble(d->d).sum());// 求最和 (数字Stream才有此方法)
System.out.println(Stream.of("a", "bb", "ccc").collect(Collectors.summingInt(s->{return s.length();}))); // 求总和(元素中的某个属性返回Int)输出:6
System.out.println(Stream.of(-1.5, 1.0, -3.0, -2.0).mapToDouble(d->d).average().getAsDouble());// 求平均数 -1.375 (数字Stream才有此方法)
System.out.println(Stream.of(-1.5, 1.0, -3.0, -2.0).collect(Collectors.averagingDouble((d) -> { return d; })));// 计算平均值,返回Double类型
System.out.println(Stream.of(-1.5, 1.0, -3.0, -2.0).mapToDouble(d->d).distinct().max().getAsDouble());// 数字去重 1.0
System.out.println(Stream.of(-1.5, 1.0, -3.0, -2.0).min(Comparator.naturalOrder()));// 求最小值,minValue = -3.0 通过对 Stream 元素先排序,再 findFirst 来实现
System.out.println(Stream.of(-1.5, 1.0, -3.0, -2.0).count());// 求集合的size
/**
* 4.Collectors的使用
*/
// groupingBy()
Map<Integer, List<String>> collect = Stream.of("a", "bb", "c").collect(Collectors.groupingBy((a) -> {return a.length();}));// 分组,默认是元素集合类型的
Map<Integer, Set<String>> collectSet = Stream.of("a", "bb", "c").collect(Collectors.groupingBy((a) -> {return a.length();},Collectors.toSet()));// 分组, ,Collectors.toSet()表示map的value是Set<T>集合,而不是List<t>
Map<Integer, Long> collectCount = Stream.of("a", "bb", "c").collect(Collectors.groupingBy((a) -> {return a.length();},Collectors.counting()));// 分组, ,Collectors.counting()表示map的value是Long的数量
System.out.println(Stream.of("a", "bb", "c").collect(Collectors.groupingBy((a) -> {return a.length();})));// 分组 输出:{1=[a, c], 2=[bb]}
System.out.println(Stream.of("a", "bb", "c").collect(Collectors.groupingByConcurrent(String::length))); // 分组groupingBy的并发版本 输出:{1=[a, c], 2=[bb]}
// partitioningBy()
Map<Boolean, List<String>> collect1 = Stream.of("a", "bb", "c").collect(Collectors.partitioningBy((a) -> { return a.length() > 1; }));// 分成2部分 true是返回符合条件的,false是其余部分
System.out.println(collect1); // {false=[a, c], true=[bb]}
Map<String, String> collect2 = Stream.of("a", "bb", "ccc").collect(Collectors.toMap(key -> { return key; }, Function.identity()));// 返回的Map的key不能有重复,也就是toMap()的keyMapper不能重复,有重复会抛出异常
System.out.println(collect2); // {bb=bb, a=a, ccc=ccc}
ArrayList<String> collect3 = Stream.of("a", "b", "c").collect(Collectors.toCollection(() -> { return new ArrayList<>(); }));// 返回 new的对象的集合
Stream.of("a", "b", "c").collect(Collectors.toCollection(HashSet::new));
System.out.println(collect3); // [a, b, c]
String collect4 = Stream.of("a", "b", "c").collect(Collectors.joining());// 字符串集合组合成一个字符串,只适合字符串集合的
System.out.println(collect4); // abc
String collect5 = Stream.of("a", "b", "c").collect(Collectors.joining("|"));// 字符串集合组合成一个字符串,且用界定符或连接符进行连接
System.out.println(collect5); // a|b|c
String collect6 = Stream.of("a", "b", "c").collect(Collectors.joining("连接符", "前缀", "后缀"));
System.out.println(collect6); // 前缀a连接符b连接符c后缀
Optional<String> collect7 = Stream.of("a", "bb", "ccc").max(Comparator.comparingInt(String::length)); // 获取最多哪个元素对象
System.out.println(collect7.get()); // .get()返回集合元素中的一个对象
String collect8 = Stream.of("a", "bb", "ccc").collect(Collectors.collectingAndThen(Collectors.maxBy((a, b) -> { return a.length() - b.length(); }), Optional::get));
System.out.println(collect8);//ccc
String collect9 = Stream.of("a", "bb", "ccc").collect(Collectors.collectingAndThen(Collectors.minBy((a, b) -> { return a.length() - b.length(); }), Optional::get));
System.out.println(collect9);//a
System.out.println(Stream.of("a", "bb", "c").collect(Collectors.counting())); // 计算数量 输出:3
Stream.of("a", "bb", "c").collect(Collectors.mapping(o -> o, Collectors.joining("||")));// 和下面一行一样的意思 a||bb||c
Stream.of("a", "bb", "c").map(o -> o).collect(Collectors.joining("||"));
/**
* 概要统计(Int,Double,Long)
*/
IntSummaryStatistics collect10 = Stream.of("a", "bb", "c").collect(Collectors.summarizingInt(String::length));//Int概要统计对象
System.out.println(collect10.getAverage());//1.3333333333333333
System.out.println(collect10.getCount());//3
System.out.println(collect10.getSum());//4
System.out.println(collect10.getMax());//2
System.out.println(collect10.getMin());//1
/**
* 流的短路
*
* 包括的操作:anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit
*
* Stream 有三个 match 方法,从语义上说:
* allMatch:Stream 中全部元素符合传入的 predicate,返回 true
* anyMatch:Stream 中只要有一个元素符合传入的 predicate,返回 true
* noneMatch:Stream 中没有一个元素符合传入的 predicate,返回 true
*/
System.out.println(Stream.of("a", "bb", "c").allMatch(s -> {return s.length()>0;}));//true
System.out.println(Stream.of("a", "bb", "c").anyMatch(s -> {return s.length()==2;}));//true
System.out.println(Stream.of("a", "bb", "c").noneMatch(s -> {return s.length()>2;}));//true
System.out.println(Stream.of("a", "bb", "c").findAny().get());//找到任何一个,一般是第一个 a
System.out.println(Stream.of("a", "bb", "c").findFirst().get());//找到第一个 a
System.out.println(Stream.of("a", "bb", "c").limit(3).collect(Collectors.toList()));//第一个到第3个元素获取
}
Java 8 Stream Distinct Examples
//非对象去重
Collection<String> list = Arrays.asList("A", "B", "C", "D", "A", "B", "C");
// Get collection without duplicate i.e. distinct only
List<String> distinctElements = list.stream().distinct().collect(Collectors.toList());
//Let's verify distinct elements
System.out.println(distinctElements);
//对象去重
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class JavaStreamDistinctExamples
{
public static void main(String[] args)
{
Person lokesh = new Person(1, "Lokesh", "Gupta");
Person brian = new Person(2, "Brian", "Clooney");
Person alex = new Person(3, "Alex", "Kolen");
//Add some random persons
Collection<Person> list = Arrays.asList(lokesh,brian,alex,lokesh,brian,lokesh);
// Get distinct only
List<Person> distinctElements = list.stream().filter(distinctByKey(p -> p.getId())).collect(Collectors.toList());
// Let's verify distinct elements
System.out.println(distinctElements);
}
public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor)
{
Map<Object, Boolean> map = new ConcurrentHashMap<>();
return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
}
class Person
{
public Person(Integer id, String fname, String lname) {
super();
this.id = id;
this.fname = fname;
this.lname = lname;
}
private Integer id;
private String fname;
private String lname;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFname() {
return fname;
}
public void setFname(String fname) {
this.fname = fname;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
@Override
public String toString() {
return "Person [id=" + id + ", fname=" + fname + ", lname=" + lname + "]";
}
}
Program Output:
[
Person [id=1, fname=Lokesh, lname=Gupta],
Person [id=2, fname=Brian, lname=Clooney],
Person [id=3, fname=Alex, lname=Kolen]
]
public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor)
{
Map<Object, Boolean> map = new ConcurrentHashMap<>();
System.out.println("我输出了一次,我是在循环之外的");
// 说明
// t就是Stream流的对象,t->{return true/false}是对Predicate的test(t)的实现,t是test(T)方法的入参,{return true/false}是test()的实现或说是方法体
// 而本方法的Function keyExtractor对象的实现(p -> p.getName()),
// 其中p就是Stream流的对象和t是同一个概念,(p -> p.getName())是针对Function的app(T)的实现,p是app(T)方法的入参是个对象, p.getName()是对app()的实现
return t ->{
System.out.println("我输出了W次"+t);
System.out.println("我输出了N次"+keyExtractor.apply(t));
return map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
};
//结果
//我输出了一次
//我输出了W次com.bean.Student@181eb93
//我输出了N次1
//我输出了W次com.bean.Student@91c18f
//我输出了N次1
//我输出了W次com.bean.Student@a245ab
//我输出了N次1
}

浙公网安备 33010602011771号