Java 8 中的谓词
筛选隐藏文件
/**
* 筛选隐藏文件
*
* @param path
* @return
*/
File[] listHiddenFiles2(String path) {
return new File(path).listFiles(File::isHidden);
}
filter
谓词使用代码示例:
/**
* LambdaDemo.java
*/
package study.java8.lambda;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.Predicate;
/**
* @author jack 2016年8月18日 下午2:16:53
*/
public class LambdaDemo {
/**
* @param args
*/
public static void main(String[] args) {
List<Integer> nums = Arrays.asList(1,
23,
4,
56,
7,
8,
10);
// 用stream api
nums.stream()
.sorted()
.forEach(System.out::println);
// lambda表达式本质上也是Collections.sort方法
nums.sort((e1, e2) -> e1.compareTo(e2));
nums.forEach(System.out::println);
// 内部类,Collections.sort方法
nums.sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
});
List<String> languages = Arrays.asList("Java",
"Scala",
"C++",
"Haskell",
"Lisp");
System.out.println("Languages which starts with J :");
filter(languages,
(str) -> str.startsWith("J"));
System.out.println("Languages which ends with a ");
filter(languages,
(str) -> str.endsWith("a"));
System.out.println("Print all languages :");
filter(languages,
(str) -> true);
System.out.println("Print no language : ");
filter(languages,
(str) -> false);
System.out.println("Print language whose length greater than 4:");
filter(languages,
(str) -> str.length() > 4);
}
public static void filter(List<String> names, Predicate<String> condition) {
for (String name : names) {
if (condition.test(name)) {
System.out.println(name + " ");
}
}
}
}
:: 与 ->
java8函数式编程中引进了::与->这两个关键字.
这个双冒号, 是传递函数的.由编译器解释,而不是由JVM运行时. 具体实现原理可以通过分析class文件看.
代码示例:
/**
* FunctionalInterfaceDemo.java
*/
package study.java8.fp;
/**
* @author jack 2016年8月16日 下午3:57:58
*/
public class FunctionalInterfaceDemo {
String startWith(String s) {
return s.valueOf(s.charAt(0));
}
/**
* @param args
*/
public static void main(String[] args) {
FunctionalInterfaceDemo DoubleColons = new FunctionalInterfaceDemo();
Converter<String, String> converter = DoubleColons::startWith;
String cc = converter.convert("Scala");
System.out.println(cc);
}
}
@FunctionalInterface
interface Converter<F, T> {
T convert(F from);
}
注解@FunctionalInterface
函数式接口就是只包含一个函数方法的接口.一般用@FunctionalInterface这个注解标记.
当然, 这个接口里面可以包含默认方法, 静态方法等.
@FunctionalInterface
public interface FileFilter {
/**
* Tests whether or not the specified abstract pathname should be
* included in a pathname list.
*
* @param pathname The abstract pathname to be tested
* @return <code>true</code> if and only if <code>pathname</code>
* should be included
*/
boolean accept(File pathname);
}
Predicate接口
Predicate和Consumer接口的test()和accept()方法都接受一个泛型参数。不同的是test()方法进行某些逻辑判断并返回一个boolean值,而accept()接受并改变某个对象的内部值。
/**
* AppleFilter.java
*/
package study.java8.fp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
/**
* @author jack 2016年8月10日 下午5:30:53
*/
public class AppleFilter {
public static List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> p) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if (p.test(apple)) {
result.add(apple);
}
}
return result;
}
/**
* @param args
*/
public static void main(String[] args) {
List<Apple> inventory = Arrays.asList(new Apple(80, "green"), new Apple(155, "green"), new Apple(120, "red"));
List<Apple> greenApples = filterApples(inventory, AppleFilter::isGreenApple);
System.out.println(greenApples);
List<Apple> heavyApples = filterApples(inventory, AppleFilter::isHeavyApple);
System.out.println(heavyApples);
List<Apple> greenApples2 = filterApples(inventory, (Apple a) -> isGreenApple(a));
System.out.println(greenApples2);
List<Apple> heavyApples2 = filterApples(inventory, (Apple a) -> isHeavyApple(a));
System.out.println(heavyApples2);
List<Apple> weirdApples = filterApples(inventory,
(Apple a) -> a.getWeight() < 80 || "brown".equals(a.getColor()));
System.out.println(weirdApples);
}
public static List<Apple> filterGreenApples(List<Apple> inventory) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if (isGreenApple(apple)) {
result.add(apple);
}
}
return result;
}
public static List<Apple> filterHeavyApples(List<Apple> inventory) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if (isHeavyApple(apple)) {
result.add(apple);
}
}
return result;
}
/////////////////////////////////////////////////
public static boolean isGreenApple(Apple apple) {
return "green".equals(apple.getColor());
}
public static boolean isHeavyApple(Apple apple) {
return apple.getWeight() > 150;
}
public static class Apple {
private int weight = 0;
private String color = "";
public Apple(int weight, String color) {
this.weight = weight;
this.color = color;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String toString() {
return "Apple{" + "color='" + color + '\'' + ", weight=" + weight + '}';
}
}
}
这里的::指向Predictable接口:
package java.util.function;
import java.util.Objects;
/**
* Represents a predicate (boolean-valued function) of one argument.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #test(Object)}.
*
* @param <T> the type of the input to the predicate
*
* @since 1.8
*/
@FunctionalInterface
public interface Predicate<T> {
/**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
boolean test(T t);
/**
* Returns a composed predicate that represents a short-circuiting logical
* AND of this predicate and another. When evaluating the composed
* predicate, if this predicate is {@code false}, then the {@code other}
* predicate is not evaluated.
*
* <p>Any exceptions thrown during evaluation of either predicate are relayed
* to the caller; if evaluation of this predicate throws an exception, the
* {@code other} predicate will not be evaluated.
*
* @param other a predicate that will be logically-ANDed with this
* predicate
* @return a composed predicate that represents the short-circuiting logical
* AND of this predicate and the {@code other} predicate
* @throws NullPointerException if other is null
*/
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
/**
* Returns a predicate that represents the logical negation of this
* predicate.
*
* @return a predicate that represents the logical negation of this
* predicate
*/
default Predicate<T> negate() {
return (t) -> !test(t);
}
/**
* Returns a composed predicate that represents a short-circuiting logical
* OR of this predicate and another. When evaluating the composed
* predicate, if this predicate is {@code true}, then the {@code other}
* predicate is not evaluated.
*
* <p>Any exceptions thrown during evaluation of either predicate are relayed
* to the caller; if evaluation of this predicate throws an exception, the
* {@code other} predicate will not be evaluated.
*
* @param other a predicate that will be logically-ORed with this
* predicate
* @return a composed predicate that represents the short-circuiting logical
* OR of this predicate and the {@code other} predicate
* @throws NullPointerException if other is null
*/
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
/**
* Returns a predicate that tests if two arguments are equal according
* to {@link Objects#equals(Object, Object)}.
*
* @param <T> the type of arguments to the predicate
* @param targetRef the object reference with which to compare for equality,
* which may be {@code null}
* @return a predicate that tests if two arguments are equal according
* to {@link Objects#equals(Object, Object)}
*/
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}