Java8新特性

196 阅读7分钟

1.接口与Lambda 表示式

函数式接口(FunctionalInterface): 就是只包含一个抽象方法的声明,用@FunctionalInterface表示, 常见的有Comparator, Predicate, Function, Supplier, Consumer,只有函数式接口才能缩写成 Lambda 表示式

@FunctionalInterface
interface HelloDemo {

	public abstract void sayHi();

	// 接口内可以定义默认方法, 默认方法不算抽象方法,因为它有方法体
	public default void sayGood() {
		System.out.println("you are so good ...");
	}

	// 接口内可以定义静态方法
	public static void sayGoodAndHi() {
		System.out.println("hi, you are so good ..");
	}
}

class HelloEveryOne implements HelloDemo {
    @Override
	public void sayHi() {
		// TODO Auto-generated method stub
	}
	
	public static void main(String[] args) {
		// 默认方法不强制实现,实现类能够直接使用
		HelloEveryOne helloEveryOne = new HelloEveryOne();
		helloEveryOne.sayGood();
		// lambda表达式常见用法
		HelloDemo helloDemo = (() -> System.out.println("haha ++++++++++++++")); // 重写sayHi方法
		helloDemo.sayHi();
		List<String> list = Arrays.asList("a", "c", "b");
		list.sort((a, b) -> a.compareTo(b)); // 升序
		list.forEach(a -> System.out.println(a));
		list.forEach(System.out::println); // 使用::调用静态方法
	}
}

2.Predicate

Predicate: 是一个可以指定入参类型,并返回 boolean 值的函数式接口。它内部提供了一些带有默认实现的方法,可以被用来组合一个复杂的逻辑判断(and, or, negate)

// and 相当于 && 能断路
default Predicate<T> and(Predicate<? super T> other) {
	        Objects.requireNonNull(other);
	        return (t) -> test(t) && other.test(t);
}

Predicate<String> predicate = (s) -> s != null;
Predicate<String> predicate2 = (s) -> !s .equals("");
Predicate<String> predicate3 = predicate.and(predicate2);
boolean flag = predicate3.test(null);

// or 相当于 || 能断路
default Predicate<T> or(Predicate<? super T> other) {
	 Objects.requireNonNull(other);
	 return (t) -> test(t) || other.test(t);
}

Predicate<String> predicate = (s) -> s != null;
Predicate<String> predicate2 = (s) -> !s.equals("");
Predicate<String> predicate3 = predicate.or(predicate2);
boolean flag = predicate3.test(null);

// negate 相当于 !
default Predicate<T> negate() {
	return (t) -> !test(t);
}

Predicate<String> predicate2 = (s) -> s.equals("");
boolean flag = predicate2.negate().test("a");

// isEqual判断两个值是否相等
static <T> Predicate<T> isEqual(Object targetRef) {
	   return (null == targetRef) ? Objects::isNull
	                 : object -> targetRef.equals(object);
}
boolean flag = Predicate.isEqual(null).test("");

3.Function

Function: 对元素进行功能处理,如:类型转换,字母大小写切换

Function<String, Integer> toInteger = Integer::valueOf;
Function<String, String> toUpperCase = String::toUpperCase;
Function<String, String> backToString = toInteger.andThen(String::valueOf);
Function<String, Integer> composeToString =toInteger.compose(String::valueOf);
// apply() 调用当前Function函数接口并传入参数,返回结果
String a = backToString.apply("123");     // "123"
Integer b = composeToString.apply("123"); // 123

// 先执行传入的Function函数接口,然后再执行当前Function函数接口
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
    Objects.requireNonNull(before);
	return (V v) -> apply(before.apply(v));
}

// 先执行当前Function函数接口,然后再执行传入的Function函数接口
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
	Objects.requireNonNull(after);
	return (T t) -> after.apply(apply(t));
}

// 产生一个输入参数类型与输出参数类型相同的Function函数接口
static <T> Function<T, T> identity() {
	return t -> t;
}

// 将String转成Integer
ToIntFunction<String> toIntFunction = Integer::parseInt;
int c = toIntFunction.applyAsInt("2");

// 将String转成Long
ToLongFunction<String> toLongFunction = Long::parseLong;
long d = toLongFunction.applyAsLong("43");

// 将String转成Double
ToDoubleFunction<String> toDoubleFunction = Double::parseDouble;
double f = toDoubleFunction.applyAsDouble("5");

4.Supplier

Supplier生产者: 它不接受入参,直接为我们生产一个指定的结果

// 调用TestJava类的构造方法生成对象
Supplier<TestJava> personSupplier = TestJava::new;
TestJava testJava = personSupplier.get();  

// 调用TestJava类的getMessage方法
Supplier<String> supplier = TestJava::getMessage;
// 获得getMessage的返回值
System.out.println(supplier.get()); 

5.Consumer

Consumer消费着:接受入参,用来被消费

lass HelloEveryOne {

	private String firstName;

	private String lastName;

	private int age;

	private int classId;

	/**
	 * @return the age
	 */
	public int getAge() {
		return age;
	}

	/**
	 * @param age the age to set
	 */
	public void setAge(int age) {
		this.age = age;
	}

	/**
	 * @return the classId
	 */
	public int getClassId() {
		return classId;
	}

	/**
	 * @param classId the classId to set
	 */
	public void setClassId(int classId) {
		this.classId = classId;
	}

	/**
	 * @return the firstName
	 */
	public String getFirstName() {
		return firstName;
	}

	/**
	 * @param firstName the firstName to set
	 */
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	/**
	 * @return the lastName
	 */
	public String getLastName() {
		return lastName;
	}

	/**
	 * @param lastName the lastName to set
	 */
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public HelloEveryOne() {

	}

	public HelloEveryOne(String firstName, String lastName) {
		this.firstName = firstName;
		this.lastName = lastName;
	}

	public HelloEveryOne(int age, int classId, String firstName, String lastName) {
		this.age = age;
		this.classId = classId;
		this.firstName = firstName;
		this.lastName = lastName;
	}


	public String say() {
		return "say";
	}

}

Consumer<HelloEveryOne> greeter = (p) -> System.out.println("Hello, " + p.getFirstName());
Consumer<HelloEveryOne> greeter2 = (p) -> System.out.println("Hello, " + p.getLastName());
// 传入参数并调用该Consumer定义的方法
greeter.accept(new HelloEveryOne("Luke", "Skywalker"));

// 先调用当前Consumer定义的方法,然后调用andThen里面Consumer定义的方法
greeter.andThen(greeter2).accept(new HelloEveryOne("Luke", "Skywalker"));

6.Comparator

Comparator<HelloEveryOne> comparator = (p1, p2) -> p1.getFirstName().compareTo(p2.getFirstName());
HelloEveryOne p1 = new HelloEveryOne(2, 1, "John", "Doe");
HelloEveryOne p2 = new HelloEveryOne(2, 2, "Alice", "Wonderland");
int a = comparator.compare(p1, p2);             // 相当于p1.getFirstName().compareTo(p2.getFirstName), 返回两个参数相差多少
int b = comparator.reversed().compare(p1, p2);  // 相当于p2.getFirstName().compareTo(p1.getFirstName), 返回两个参数相差多少


Comparator<HelloEveryOne> ageComparator = (p3, p4) -> p3.getAge() - p4.getAge();
Comparator<HelloEveryOne> classIdComparator = (p5, p6) -> p5.getClassId() - p6.getClassId();
// 先比较年龄,如果年龄相同,再继续比较班级id
int c = ageComparator.thenComparing(classIdComparator).compare(p1, p2);
System.out.println(c); // 结果: -1

// 先将比较的值类型转换,然后再比较
default <U extends Comparable<? super U>> Comparator<T> thenComparing(
    Function<? super T, ? extends U> keyExtractor)
	{
	   return thenComparing(comparing(keyExtractor));
	}

// 先将比较的值转成int,然后再比较
default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor) {
    return thenComparing(comparingInt(keyExtractor));
}

// 先将比较的值转成long,然后再比较
default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor) {
    return thenComparing(comparingLong(keyExtractor));
}

// 先将比较的值转成double,然后再比较
default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor) {
    return thenComparing(comparingDouble(keyExtractor));
}

// 用于处理比较值为null情况下,避免抛出异常
// 如果第一个值为null,第二个值不为null,返回-1
// 如果第一个值不为null,第二个值为null,返回1
// 如果两个值都为null,返回0
// 如果比较器为null,返回0,其他情况按compare()比较
public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) {
    return new Comparators.NullComparator<>(true, comparator);
}

// 如果第一个值为null,第二个值不为null,返回1
// 如果第一个值不为null,第二个值为null,返回-1
// 如果两个值都为null,返回0
// 如果比较器为null,返回0,其他情况按compare()比较
public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) {
    return new Comparators.NullComparator<>(false, comparator);
}
NullComparator(boolean nullFirst, Comparator<? super T> real) {
    this.nullFirst = nullFirst;
    this.real = (Comparator<T>) real;
}

@Override
public int compare(T a, T b) {
    if (a == null) {
        return (b == null) ? 0 : (nullFirst ? -1 : 1);
    } else if (b == null) {
        return nullFirst ? 1: -1;
    } else {
        return (real == null) ? 0 : real.compare(a, b);
    }
}

7.Optional

Optional.ofNullable(T value): 能传null值  
Optional.of(T value): 不能传null值,否则会报NullpointerException
Optional<String> optional = Optional.ofNullable(null);

// 判断optional的值是否不为null
boolean isNotNull = optional.isPresent();

// 获取optional的值,如果为null,会报NoSuchElementException
String value = optional.get();

// 如果optional的值为null,会返回other,否则会返回optional的值
String defaultValue = optional.orElse("fallback");

8.Stream

实现了Collection接口才有stream(), Map没有

List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
list.add("1");
list.add("4");
Stream<String> stringStream = list.stream();
// 根据条件过滤
Predicate<String> predicate = s -> s.equals("a");
stringStream.filter(predicate.or(s -> s.equals("c"))).forEach(System.out::println);
stringStream.filter(s -> s.equals("d")).forEach(System.out::println);

// map():对每一个元素做功能处理,如:类型转换  mapToInt mapToLong mapToDouble
stringStream.map(Integer:: valueOf).forEach(System.out::println);
List<String> list1 = new ArrayList<>();
list1.add("4");
list1.add("5");
Map<String, List<String>> map = new HashMap<>();
map.put("list", list);
map.put("list1", list1);
Map<String, List<Integer>> map1 = new HashMap<>();

// flatMap():将多个list合并到一个list flatMapToInt flatMapToLong flatMapToDouble
map.values().stream().flatMap(l -> l.stream()).forEach(System.out::println);
map.values().stream().flatMapToInt(l -> l.stream().mapToInt(Integer::parseInt)).forEach(System.out::println);
map.values().stream().flatMapToLong(l -> l.stream().mapToLong(Long::parseLong)).forEach(System.out::println);
map.values().stream().flatMapToDouble(l -> l.stream().mapToDouble(Double::parseDouble)).forEach(System.out::println);

// distinct():将list中的元素去重
list.stream().distinct().forEach(System.out::println);

// sorted():升序排列
list.stream().sorted().forEach(System.out::println);
list.stream().sorted(((a, b) -> (b.compareTo(a)))).forEach(System.out::println);

// peek():为集合中的元素添加功能行为
list.stream().filter(e -> e.equals("1"))
	.peek(e -> System.out.println("Filtered value: " + e))
	.map(String::toUpperCase)
	.peek(e -> System.out.println("Mapped value: " + e))
	.collect(Collectors.toList());

// limit(): 控制返回结果条数,和mongodb数据库的limit意义一样
list.stream().filter(e -> !e.equals("2")).limit(2).forEach(System.out::println);

// skip(): 跳过多少条,和mongodb数据库的skip意义一样
list.stream().skip(1).forEach(System.out::println);

// for循环 :
forEach(Consumer<? super T> action)
forEachOrdered(Consumer<? super T> action);
stringStream.forEach((s) -> System.out.println("ooo " +s));
stringStream.forEachOrdered((s) -> System.out.println("ooo " +s));

// Object[] toArray(); 
toArray(IntFunction<A[]> generator)
List<Integer> intList = Arrays.asList(1, 3, 5);
Integer[] array = intList.stream().toArray(Integer[]::new);
int[] arr = intList.stream().mapToInt(Integer::new).toArray();
String[] stringArr = stringStream.toArray(String[]::new);

reduce(T identity, BinaryOperator<T> accumulator);
reduce(U identity, BiFunction<U, ? super T, U> accumulator,     BinaryOperator<U> combiner)
reduce(BinaryOperator<T> accumulator)
int sum = intList.stream().reduce(0, Integer::sum);
intList.stream().reduce((a, b) -> a*b).ifPresent(System.out::println);
// 注意:它们的计算结果必须和stream中的元素类型相同,如上面的代码示例,stream中的类型为int,那么计算结果也必须为int,这导致了灵活性的不足,甚至无法完成某些任务, 比入我们咬对一个一系列int值求和,但是求和的结果用一个int类型已经放不下,必须升级为long类型,此实第三签名就能发挥价值了,它不将执行结果与stream中元素的类型绑死。

long result = intList.stream().reduce(0L,(a,b) ->  a + b, (a,b)-> 0L );
List<Integer> numList = Arrays.asList(1, 2, 3, 4, 5, 6);
ArrayList<String> result2 = numList.stream().reduce(new ArrayList<String>(), (a, b) -> {
	a.add("element-" + Integer.toString(b));
	return a;
}, (a, b) -> null);

collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner);
collect(Collector<? super T, A, R> collector)

// 将list转set
Set<String> set = stringStream.collect(Collectors.toSet());

// 生成新的list
List<String> newList = stringStream.collect(Collectors.toList());

// 将元素等于“1”的分成一组,其他分成一组
stringStream.collect(Collectors.groupingBy(a -> a.equals("1")));

// 将集合分割成两部分,true为等于“1”的元素, false为不等于“1”的元素
Map<Boolean, List<String>> resultMap = stringStream.collect(Collectors.partitioningBy(a -> a.equals("1")));

// 将list以,拼接生成字符串
String res = stringStream.collect(Collectors.joining(","));

// 获取并行流: 并行流是通过多线程来处理的,能够充分利用多核CPU 的优势,处理速度更快。
list.parallelStream();

// 统计集合元素个数
long res = list.stream.count();