java8filter

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

/**
 * @author Kyle
 * @version 1.0 2018年8月9日
 *          NEW java.util.function.Predicate<T>
 *          接口定义了一个名叫test的抽象方法,它接受泛型
 *          T对象,并返回一个boolean。这恰恰和你先前创建的一样,现在就可以直接使用了。在你需要
 *          表示一个涉及类型T的布尔表达式时,就可以使用这个接口。比如,你可以定义一个接受String 对象的Lambda表达式
 * @function Predicate 谓词
 */
public class MyPredicate {
   
//     jdk8自带的接口
// @FunctionalInterface
// public interface Predicate<T> {
//    boolean test(T t);
// }

   // 要筛选的list, p带筛选条件的对象,此处的p应该用Lambda(匿名函数)表达式来实现Predicate<T>接口
   public static <T> List<T> filter(List<T> list, Predicate<T> p) {
      List<T> results = new ArrayList<>();
      for (T s : list) {
         if (p.test(s)) {
            results.add(s);
         }
      }
      return results;
   }

   public static void main(String[] args) {
      Predicate<String> nonEmptyStringPredicate = (String s) -> !s.isEmpty();
        
      // Predicate<String> nonEmptyStringPredicate 是接口定义
      // (String s) -> !s.isEmpty(); 是对接口的实现,实现的方法是boolean test(T t); 返回一个boolean值
      List<String> listOfStrings = new ArrayList<>();
      listOfStrings.add(new String());
      listOfStrings.add(new String("123"));
      listOfStrings.add(new String("555"));
      
      // 可以直接写实现
      List<String> nonEmpty = filter(listOfStrings, (String s) -> s.isEmpty()); // 字符串是空的
      System.out.println("空串元素的size: "+nonEmpty.size());
      
      // 也可以用对象引用代替
      
      List<String> nonEmpty2 = filter(listOfStrings, nonEmptyStringPredicate);
      
      System.out.println("非空窜的size:"+nonEmpty2.size());
      
      List<Apple> listApple = new ArrayList<>();
      listApple.add(new Apple("green", 100));
      listApple.add(new Apple("gray", 150));
      listApple.add(new Apple("red", 200));
      listApple.add(new Apple("red", 150));
      listApple.add(new Apple("black", 50));
      
      Predicate<Apple> applePredicate = (Apple a) -> a.getWeight() > 100 && "red".equals(a.getColor());
      
      /*  请注意,当Lambda仅有一个类型需要推断的参数时,参数名称两边的括号也可以省略,
         Lambda 类型推断
         你还可以进一步简化你的代码。Java编译器会从上下文(目标类型)推断出用什么函数式接
         口来配合Lambda表达式,这意味着它也可以推断出适合Lambda的签名,因为函数描述符可以通
         过目标类型来得到。这样做的好处在于,编译器可以了解Lambda表达式的参数类型,这样就可
         以在Lambda语法中省去标注参数类型。换句话说,Java编译器会像下面这样推断Lambda的参数
         类型:①
         List<Apple> greenApples = filter(inventory, a -> "green".equals(a.getColor()));
      */
      
      // Predicate<Apple> applePredecate = a -> a.getWeight() > 100 && "red".equals(a.getColor());
      // 请注意,当Lambda仅有一个类型需要推断的参数时,参数名称两边的括号也可以省略
      
      // List<Apple> lsApple = filter(listApple, (Apple a) -> a.getWeight() > 100 && "red".equals(a.getColor())); // 直接写实现
      List<Apple> lsApple = filter(listApple, applePredicate);
      System.out.println("大于100的红色: "+lsApple.size());
      
      /*
         Lambda 对局部变量的限制,只能引用final 修饰的变量,或者隐式最终(隐式最终就是只能给变更赋值一次)
         你可能会问自己,为什么局部变量有这些限制。第一,实例变量和局部变量背后的实现有一
         个关键不同。实例变量都存储在堆中,而局部变量则保存在栈上。如果Lambda可以直接访问局
         部变量,而且Lambda是在一个线程中使用的,则使用Lambda的线程,可能会在分配该变量的线
         程将这个变量收回之后,去访问该变量。因此,Java在访问自由局部变量时,实际上是在访问它
         的副本,而不是访问原始变量。如果局部变量仅仅赋值一次那就没有什么区别了——因此就有了
         这个限制。
      */
      
      // negate
      Predicate<Apple> redApple = (Apple a) -> "red".equals(a.getColor());
      List<Apple> lsRedApple = filter(listApple, redApple.negate());  // 非redApple.negate(),本来是比较苹果是红色的,加了就是negate()取返,相当于!=(不等)
      System.out.println("非红色个数: "+lsRedApple.size());
      
      // and 链接两个谓词来生成另一个Predicate对象
      Predicate<Apple> redAndHeavyApple = redApple.and(a -> a.getWeight() > 150); // redApple = (Apple a) -> "red".equals(a.getColor()); 与的关系
      lsRedApple = filter(listApple, redAndHeavyApple);
      System.out.println("appple-red and getWeight() > 150 : "+lsRedApple.size());
      
      // and or 
      Predicate<Apple> redAndHeavyAppleOrGreen =
            redApple.and(a -> a.getWeight() > 150)
            .or(a -> "green".equals(a.getColor())); // 一个参数可以省略(),参数的类型也可以通过Predicate<Apple>推导,所以只写了个a ->
      
      lsRedApple = filter(listApple, redAndHeavyAppleOrGreen);
      
      System.out.println("appple-red and getWeight() > 150 或者为绿色 : "+lsRedApple.size());
      
   }
}

class Apple {
   public int weight;
   public String color;
   
   public Apple(String color, int weight){
      this.color = color;
      this.weight = weight;
   }
   public int getWeight() {
      return weight;
   }
   public void setWeight(int weight) {
      this.weight = weight;
   }
   public String getColor() {
      return color;
   }
   public void setColor(String color) {
      this.color = color;
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值