0
点赞
收藏
分享

微信扫一扫

Lambda表达式(二)


  • 在上一节中,我们为了使用 Lambda 表达式不得不创建了各种函数描述符的函数式接口,其实 Java 8 已经给我们提供了一套能够描述常见函数描述符的函数式接口
  • 比如​​Predicate<T>​​​、​​Consumer<T>​​​、​​Function<T,R>​​​、​​Supplier<T>​​​ 等,这些函数式接口位于​​java.util.function​​ 包
  • 这一节主要记录这些函数式接口的应用


Java8中的函数式接口


  • 下面的表格列出了 Java8 中常见的函数式接口:


函数式接口

函数描述符

原始类型特化

Predicate

T -> boolean

IntPredicate, LongPredicate, DoublePredicate

Consumer

T -> void

IntConsumer, LongConsumer, DoubleConsumer

Function<T, R>

T -> R

IntFunction, IntToDoubleFunction, IntToLongFunction,

LongFunction, LongToDoubleFunction, LongToIntFunction,

DoubleFunction, ToIntFunction, ToDoubleFunction, ToLongFunction

Supplier

() -> T

BooleanSupplier, IntSupplier, LongSupplier, DoubleSupplier

UnaryOperator

T -> T

IntUnaryOperator, LongUnaryOperator, DoubleUnaryOperator

BinaryOperator

(T, T) -> T

IntBinaryOperator, LongBinaryOperator, DoubleBinaryOperator

BiPredicate<L, R>

(L, R) -> boolean

BiConsumer<T, U>

(T, U) -> void

ObjIntConsumer, ObjLongConsumer, ObjDoubleConsumer

BiFunction<T, U, R>

(T, U) -> R

ToIntBiFunction<T, U>, ToLongBiFunction<T, U>, ToDoubleBiFunction<T, U>

Predicate


  • predicate: 英 [ˈpredɪkət] 美 [ˈpredɪkət] 断言,断定的意思
  • 从接口的名称就可以推断出这个函数式接口的主要作用就是用于判断作用,Predicate 源码如下所示:


@FunctionalInterface
public&nbsp;interface&nbsp;Predicate&lt;T&gt;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;boolean&nbsp;test(T&nbsp;t);

&nbsp;&nbsp;&nbsp;&nbsp;default&nbsp;Predicate&lt;T&gt;&nbsp;and(Predicate&lt;?&nbsp;super&nbsp;T&gt;&nbsp;other)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Objects.requireNonNull(other);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(t)&nbsp;-&gt;&nbsp;test(t)&nbsp;&amp;&amp;&nbsp;other.test(t);
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;default&nbsp;Predicate&lt;T&gt;&nbsp;negate()&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(t)&nbsp;-&gt;&nbsp;!test(t);
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;default&nbsp;Predicate&lt;T&gt;&nbsp;or(Predicate&lt;?&nbsp;super&nbsp;T&gt;&nbsp;other)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Objects.requireNonNull(other);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(t)&nbsp;-&gt;&nbsp;test(t)&nbsp;||&nbsp;other.test(t);
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;&lt;T&gt;&nbsp;Predicate&lt;T&gt;&nbsp;isEqual(Object&nbsp;targetRef)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(null&nbsp;==&nbsp;targetRef)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;Objects::isNull
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;object&nbsp;-&gt;&nbsp;targetRef.equals(object);
&nbsp;&nbsp;&nbsp;&nbsp;}
}


  • 可以看到​​java.util.function.Predicate<T>​​​ 接口定义了一个名叫​​test​​​ 的抽象方法,它接受一个泛型​​T​​​ 对象,并返回一个​​boolean​​​,函数描述符为​​(T) -> boolean​​ 举几个例子
  • 偶数判断:


/**
 * @author BNTang
 **/
public&nbsp;class&nbsp;Demo&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Predicate&lt;Integer&gt;&nbsp;isEven&nbsp;=&nbsp;(in)&nbsp;-&gt;&nbsp;in&nbsp;%&nbsp;2&nbsp;==&nbsp;0;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(isEven.test(17));
&nbsp;&nbsp;&nbsp;&nbsp;}
}


  • 判断字符串的长度是否为0


/**
 * @author BNTang
 **/
public&nbsp;class&nbsp;Demo&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Predicate&lt;String&gt;&nbsp;isEmptyString&nbsp;=&nbsp;String::isEmpty;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(isEmptyString.test(&quot;&quot;));
&nbsp;&nbsp;&nbsp;&nbsp;}
}


  • 除了抽象方法外,​​java.util.function.Predicate<T>​​​ 接口还定义了三个默认方法:​​and​​​,​​negate​​​ 和​​or​​,对应 “与”,“非” 和 “或” 操作,这样我们便可以复合 Lambda 表达式了,比如:



  • 判断是偶数,并且大于30


/**
 * @author BNTang
 **/
public&nbsp;class&nbsp;Demo&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Predicate&lt;Integer&gt;&nbsp;isEven&nbsp;=&nbsp;(in)&nbsp;-&gt;&nbsp;in&nbsp;%&nbsp;2&nbsp;==&nbsp;0;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(isEven.and((in)&nbsp;-&gt;&nbsp;in&nbsp;&gt;&nbsp;30).test(40));
&nbsp;&nbsp;&nbsp;&nbsp;}
}


  • 奇数判断


/**
 * @author BNTang
 **/
public&nbsp;class&nbsp;Demo&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Predicate&lt;Integer&gt;&nbsp;isEven&nbsp;=&nbsp;(in)&nbsp;-&gt;&nbsp;in&nbsp;%&nbsp;2&nbsp;==&nbsp;0;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Predicate&lt;Integer&gt;&nbsp;isOdd&nbsp;=&nbsp;isEven.negate();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(isOdd.test(17));
&nbsp;&nbsp;&nbsp;&nbsp;}
}

Consumer


  • 英 [kənˈsju:mə(r)] 美 [kənˈsu:mə(r)] n.消费者
  • 该函数式接口用于消费一个对象,即接收一个对象,对其执行某些操作,然后没有返回值
  • Consumer 源码如下所示:


@FunctionalInterface
public&nbsp;interface&nbsp;Consumer&lt;T&gt;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;accept(T&nbsp;t);
&nbsp;&nbsp;&nbsp;&nbsp;default&nbsp;Consumer&lt;T&gt;&nbsp;andThen(Consumer&lt;?&nbsp;super&nbsp;T&gt;&nbsp;after)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Objects.requireNonNull(after);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(T&nbsp;t)&nbsp;-&gt;&nbsp;{&nbsp;accept(t);&nbsp;after.accept(t);&nbsp;};
&nbsp;&nbsp;&nbsp;&nbsp;}
}


  • 可以看到​​java.util.function.Consumer<T>​​​ 定义了一个名叫​​accept​​​ 的抽象方法,它接收一个泛型​​T​​​ 的对象,没有返回值(​​void​​​),函数描述符为​​(T) -> void​
  • 还提供了一个默认方法​​andThen​
  • 举个例子:


/**
 * @author BNTang
 **/
public&nbsp;class&nbsp;Demo&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Consumer&lt;Apple&gt;&nbsp;printAppleColor&nbsp;=&nbsp;(a)&nbsp;-&gt;&nbsp;System.out.println(a.getColor());
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printAppleColor.accept(new&nbsp;Apple(&quot;red&quot;,&nbsp;17.0));

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printAppleColor.andThen((a)&nbsp;-&gt;&nbsp;System.out.println(a.getWeight())).accept(new&nbsp;Apple(&quot;red&quot;,&nbsp;17.0));
&nbsp;&nbsp;&nbsp;&nbsp;}
}


  • 输出结果如下:


red
red
17.0

Supplier


  • supplier 英 [səˈplaɪə(r)] 美 [səˈplaɪər] n.供应商;供应者;供给者
  • 其源码如下:


@FunctionalInterface
public&nbsp;interface&nbsp;Supplier&lt;T&gt;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;get();
}


  • 可看到​​java.util.function.Supplier<T>​​​ 定义了一个名叫​​get​​​ 的抽象方法,它不接收参数,返回一个泛型​​T​​​ 的对象,函数描述符为​​() -> T​
  • 举个例子,下面的代码中需要给​​Apple​​ 提供一个无参的构造函数:


/**
 * @author BNTang
 **/
public&nbsp;class&nbsp;Demo&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Supplier&lt;Apple&gt;&nbsp;personSupplier&nbsp;=&nbsp;Apple::new;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// new Person
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;personSupplier.get();
&nbsp;&nbsp;&nbsp;&nbsp;}
}

Function


  • Function 源码如下:


@FunctionalInterface
public&nbsp;interface&nbsp;Function&lt;T,&nbsp;R&gt;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;R&nbsp;apply(T&nbsp;t);

&nbsp;&nbsp;&nbsp;&nbsp;default&nbsp;&lt;V&gt;&nbsp;Function&lt;V,&nbsp;R&gt;&nbsp;compose(Function&lt;?&nbsp;super&nbsp;V,&nbsp;?&nbsp;extends&nbsp;T&gt;&nbsp;before)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Objects.requireNonNull(before);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(V&nbsp;v)&nbsp;-&gt;&nbsp;apply(before.apply(v));
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;default&nbsp;&lt;V&gt;&nbsp;Function&lt;T,&nbsp;V&gt;&nbsp;andThen(Function&lt;?&nbsp;super&nbsp;R,&nbsp;?&nbsp;extends&nbsp;V&gt;&nbsp;after)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Objects.requireNonNull(after);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(T&nbsp;t)&nbsp;-&gt;&nbsp;after.apply(apply(t));
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;&lt;T&gt;&nbsp;Function&lt;T,&nbsp;T&gt;&nbsp;identity()&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;t&nbsp;-&gt;&nbsp;t;
&nbsp;&nbsp;&nbsp;&nbsp;}
}


  • ​java.util.function.Function<T, R>​​​ 接口定义了一个叫作​​apply​​​ 的方法,它接收一个泛型​​T​​​ 的对象,并返回一个泛型​​R​​​ 的对象,函数描述符为​​(T) -> R​
  • 举个例子:


/**
 * @author BNTang
 **/
public&nbsp;class&nbsp;Demo&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Function&lt;Apple,&nbsp;Double&gt;&nbsp;getAppleWeight&nbsp;=&nbsp;(a)&nbsp;-&gt;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;a.getWeight();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(getAppleWeight.apply(new&nbsp;Apple(17.0)));
&nbsp;&nbsp;&nbsp;&nbsp;}
}


  • Function 接口还提供了两个抽象方法​​compose​​​ 和​​andThen​​,从源码中可以看出两者的根本区别
  • 举个​​compose​​ 例子:


/**
 * @author BNTang
 **/
public&nbsp;class&nbsp;Demo&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Function&lt;Integer,&nbsp;Integer&gt;&nbsp;f&nbsp;=&nbsp;(x)&nbsp;-&gt;&nbsp;x&nbsp;+&nbsp;1;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Function&lt;Integer,&nbsp;Integer&gt;&nbsp;g&nbsp;=&nbsp;(x)&nbsp;-&gt;&nbsp;x&nbsp;*&nbsp;2;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(f.compose(g).apply(2));
&nbsp;&nbsp;&nbsp;&nbsp;}
}


  • 过程为:​​f(g(2))​​​,也就是​​1+(2*2)​
  • 举个​​andThen​​ 的例子:


/**
 * @author BNTang
 **/
public&nbsp;class&nbsp;Demo&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Function&lt;Integer,&nbsp;Integer&gt;&nbsp;f&nbsp;=&nbsp;(x)&nbsp;-&gt;&nbsp;x&nbsp;+&nbsp;1;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Function&lt;Integer,&nbsp;Integer&gt;&nbsp;g&nbsp;=&nbsp;(x)&nbsp;-&gt;&nbsp;x&nbsp;*&nbsp;2;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(f.andThen(g).apply(2));
&nbsp;&nbsp;&nbsp;&nbsp;}
}


  • 过程为:​​g(f(2))​​​,也就是​​(2+1)*2​


原始类型特化


  • 在学习 Function 接口的时候,我们定义了​​f​​ 函数:


Function&lt;Integer,&nbsp;Integer&gt;&nbsp;f&nbsp;=&nbsp;(x)&nbsp;-&gt;&nbsp;x&nbsp;+&nbsp;1;


  • x 的类型为 Integer 类型,1 为 int 类型,返回值为 Integer 类型,整个过程实际上为​​Integer.valueOf(x.intValue() + 1)​
  • 虽然编译器可以自动帮我们完成拆装箱,但这会造成不必要的性能消耗
  • 考虑到了这一点,Java8 为我们提供了 int 类型的 Function接口:​​IntFunction​


@FunctionalInterface
public&nbsp;interface&nbsp;IntFunction&lt;R&gt;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;R&nbsp;apply(int&nbsp;value);
}


  • 所以​​f​​ 最好重构为如下的方式:


IntFunction&lt;Integer&gt;&nbsp;f&nbsp;=&nbsp;(x)&nbsp;-&gt;&nbsp;x&nbsp;+&nbsp;1;


  • 剩余的原始类型特化函数式接口可参考上面的表格:


Java8中增强的Comparator


  • 在 Java8 之前,Comparator 接口用于实现简单的比较排序算法
  • 比如有如下List:


List&lt;Double&gt;&nbsp;list&nbsp;=&nbsp;new&nbsp;ArrayList&lt;&gt;();
list.add(12.3);
list.add(100.2);
list.add(3.14);
list.add(27.7);
list.add(-9.8);


  • 使用 Comparator 接口对 List 从小到大排序:


/**
 * @author BNTang
 **/
public&nbsp;class&nbsp;Demo&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;Double&gt;&nbsp;list&nbsp;=&nbsp;new&nbsp;ArrayList&lt;&gt;();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(12.3);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(100.2);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(3.14);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(27.7);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(-9.8);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Collections.sort(list,&nbsp;new&nbsp;Comparator&lt;Double&gt;()&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;int&nbsp;compare(Double&nbsp;o1,&nbsp;Double&nbsp;o2)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;o1.compareTo(o2);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(list);
&nbsp;&nbsp;&nbsp;&nbsp;}
}


  • Comparator 接口也是一个函数式接口,函数描述符为​​(T, T) -> int​​,Java8 中可以使用 Lambda 改造上面的排序方法:


/**
 * @author BNTang
 **/
public&nbsp;class&nbsp;Demo&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Collections.sort(list,&nbsp;(o1,&nbsp;o2)&nbsp;-&gt;&nbsp;o1.compareTo(o2));

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
&nbsp;&nbsp;&nbsp;&nbsp;}
}


  • Java8 对 List 提供了​​sort​​​ 方法,可以替代​​Collections.sort​​,所以上面的代码还可以简化为:


/**
 * @author BNTang
 **/
public&nbsp;class&nbsp;Demo&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.sort((o1,&nbsp;o2)&nbsp;-&gt;&nbsp;o1.compareTo(o2));

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
&nbsp;&nbsp;&nbsp;&nbsp;}
}


  • 使用​​方法的引用​​ 来进一步简化:


/**
 * @author BNTang
 **/
public&nbsp;class&nbsp;Demo&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.sort(Double::compareTo);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
&nbsp;&nbsp;&nbsp;&nbsp;}
}


  • Java8 对 Comparator 进行了增强,加入了一些实用的默认方法,比如对排序结果反转:


/**
 * @author BNTang
 **/
public&nbsp;class&nbsp;Demo&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Comparator&lt;Double&gt;&nbsp;comparator&nbsp;=&nbsp;Double::compareTo;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.sort(comparator.reversed());

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
&nbsp;&nbsp;&nbsp;&nbsp;}
}


  • 更多方法可以参考 Comparator 接口的 JavaDoc



查看 Comparator 的时候发现其虽然是函数式接口,但是却包含了 ​​compare​​​ 和 ​​equals​​ 这两个抽象方法,顿时有点懵逼,函数式接口不是只能有一个抽象方法么?查找资料后发现:函数式接口中可以额外定义多个抽象方法,但这些抽象方法签名必须和 Object 的 public 方法一样,接口最终有确定的类实现,而类的最终父类是 Object。因此函数式接口可以定义 Object 的 public 方法。


举报

相关推荐

0 条评论