1、Stream
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
+--------------------+ +------+ +------+ +---+ +-------+
| stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|
+--------------------+ +------+ +------+ +---+ +-------+
以上的流程转换为 Java 代码为:
List<Integer> transactionsIds =
widgets.stream()
.filter(b -> b.getColor() == RED)
.sorted((x,y) -> x.getWeight() - y.getWeight())
.mapToInt(Widget::getWeight)
.sum();
2、自定义sort函数
class LengthComparator implements Comparator<String>
{
public int compare(String first, String second)
{
return first.lengthQ - second.lengthO;
}
}
Arrays.sort(strings, new LengthComparatorO);
3.1、自定义set比较函数
//
public static List<ZljcZbDomain> removeDuplicateRecords(List<ZljcZbDomain> list){
Set<ZljcZbDomain> set = new TreeSet<ZljcZbDomain>(new Comparator<ZljcZbDomain>() {
@Override
public int compare(ZljcZbDomain o1, ZljcZbDomain o2) {
return o2.getGxbId().compareTo(o1.getGxbId());
}
});
set.addAll(list);
return new ArrayList<>(set);
}
4、λ表达式
对于只有一个抽象方法的接口, 需要这种接口的对象时, 就可以提供一个 lambda 表达式。这种接口称为函数式接口 ( functional interface )。
Arrays.sort (words,
(first, second) -> first.lengthO - second.lengthO) ;
public static void sort(T[] a, Comparator<? super T> c)
其中?super T 表示T的父类
@FunctionalInterface
public interface Comparator {}
因此可以用λ表达式,放入代码片段。实际上,在 Java 中, 对 lambda 表达式所能做的也只是能转换为函数式接口。
4.1、java定义的函数式接口
几个接口式函数
Java API 在java.util.fimction 包中定义了很多非常通用的函数式接口。其中一个接口
- BiFunction<T, U, R>
BiFunction<T, U, R> 描述了参数类型为 T 和 U 而且返回类型为 R 的函数。可以把我们的字符
串比较 lambda 表达式保存在这个类型的变量中: - Predicate
java.util.function 包中有一个尤其有用的接口 Predicate:
public interface Predicate<T>
{
boolean test(T t);
// Additional default and static methods
}
- Supplier
@FunctionalInterface
public interface Supplier<T> {
T get();
}
- Function<T, R>
@FunctionalInterface
public interface Function<T, R> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t);
4.2、λ表达式的变量范围和this指向
public static void repeatMessage(String text, int del ay)
{
ActionListener listener = event ->
{
System.out.println(text):
Toolkit.getDefaultToolkitO.beep():
};
new Timer(delay, listener).start0;
}
可以看到,lambda 表达式可以捕获外围作用域中变量的值。 在 Java 中,要确保所捕获的值是明确定义的,这里有一个重要的限制。在 lambda 表达式中, 只能引用值不会改变的变量。
这里有一条规则:lambda 表达式中捕获的变量必须实际上是最终变量 ( effectivelyfinal。)实际上的最终变量是指, 这个变量初始化之后就不会再为它赋新值。
在方法中,不能有两个同名的局部变量, 因此, lambda 表达式中同样也不能有同名的局部变量。
在 lambda 表达式中, this 的使用并没有任何特殊之处。lambda 表达式的作用域嵌套在 init 方法中,与出现在这个方法中的其他位置一样, lambda 表达式中 this 的含义并没有变化。
5、方法引用
表达式 System.out::println 是一个方法引用( method reference ), 它等价于 lambda 表达式 x 一> System.out.println(x)
从这些例子可以看出, 要用:: 操作符分隔方法名与对象或类名。主要有 3 种情况:
•object::instanceMethod
•Class::staticMethod
•Class/.instanceMethod
在前 2 种情况中,方法引用等价于提供方法参数的 lambda 表达式。前面已经提到,
System.out::println 等价于 x -> System.out.println(x) 类似地,Math::pow 等价于(x,y) ->Math.pow(x, y。)
对于第 3 种情况, 第 1 个参数会成为方法的目标。
例如,String::compareToIgnoreCase 等
同于 (x, y) -> x.compareToIgnoreCase(y)
对于第 3 种情况, 第 1 个参数会成为方法的目标。
例如,String::compareToIgnoreCase 等 同于 (x, y) -> x.compareToIgnoreCase(y) 0