guava Function Predicate Supplier

本文介绍了Guava库中的Function、Predicate和Supplier接口及其工具类Functions、Predicates和Suppliers。Function用于对象转换,Predicate用于过滤,Supplier则用于创建对象实例。文中通过示例展示了它们的使用方法,包括compose方法的组合功能、Predicates的in、and、or、not操作,以及Supplier的memoize和memoizeWithExpiration实现单例和超时失效功能。
摘要由CSDN通过智能技术生成

介绍下Guava中比较重要的几个类:Function、Predicate、Supplier
以及对应的工具类:Functions、Predicates、Suppliers

Function

Function是一个接口,本质是用来做转换的。主要是用apply方法把input转换为另外一个对象。一般都是用匿名内部类的方式使用。源码如下:

public interface Function<F, T> {
  T apply(@Nullable F input);
  boolean equals(@Nullable Object object);
}

java目前不支持闭包(除了java8),对于闭包,java目前只能说用匿名类,但是内部类语法的代码量比较大,如果大量用匿名类会使得代码难以阅读和维护。如果了解javascript中的function对象和apply方法,会对guava的Function类的语义理解有很重要的帮助

Fucntion的一个转换实例
将日期型,转换为字符串

        Function<Date, String> fun = new Function<Date, String>() {
            public String apply(Date input) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                return sdf.format(input);
            }
        };
        String apply = fun.apply(new Date());
        System.out.println(apply); //输出:2016-06-14 17:33:03

从上面的代码没看出来Function有啥好的地方,反而使得代码更复杂了。所以并不是所有的转换场景都适合用Function。一些简单原则是

  • 能用简单的方法,就不要用Function
  • 一般单一对象转换不需要用Function,针对集合的可以考虑使用

Function的集合实例

        ArrayList<String> lists = Lists.newArrayList("a", "b", "c");
        List<String> objects = FluentIterable.from(lists).transform(new Function<String, String>() {
            public String apply(String input) {
                return input + "-" + input;
            }
        }).toList();
        System.out.println(objects);//输出[a,-a,, b-b, c-c]

使用FluentIterable.from(list).tranfrom(Function)来转换真个集合的元素

Functions

Functions针对Function提供了一些工具类
compose
组合Function,比如Function1是把A转换为B,Function2是把B转换为C,可是用compose组合Function1和Function2,从而得到一个Function实例,把A转换为C。 compose源码如下

  public static <A, B, C> Function<A, C> compose(Function<B, C> g, Function<A, ? extends B> f) {
    return new FunctionComposition<A, B, C>(g, f);
  }

其中FunctionCompositionapply方法如下:只是组合调用了下两个Function,从而实现了A->B,B->C。最后能A->C

public C apply(A a) {
      return g.apply(f.apply(a));
    }

forMap
从一个map构建一个Function

        HashMap<String, String> map = Maps.newHashMap();
        map.put("a","11");
        map.put("b","22");
        Function<String, String> function = Functions.forMap(map);
        System.out.println(function.apply("a"));
        System.out.println(function.apply("c"));//如果key不存在就抛异常了

如果不希望key不存在抛出异常,可以用Functions.forMap(map,null)来创建Function,指明key不存在的时候返回默认值:null

Predicate

Predicate是一个接口,本质是用来做过滤的。一般也是用作匿名内部类,源码如下

public interface Predicate<T>{
  boolean apply(T input);
  boolean equals(Object object);  
}

Predicate和上面的Function 语法很相近,只是功能不一样,使用原则也和Function类似。

  • Function 做转换用
  • Predicate 做过滤用

Predicates

提供了针对Predicate的工具类
in
从list创建一个Predicate

        ArrayList<String> lists = Lists.newArrayList("a", "b", "c");
        Predicate<String> predicate = Predicates.in(lists);
        predicate.apply("a");//true
        predicate.apply("d");//false

and、or、not
可以使用and、or、not连接Predicate。形成复合条件的Predicate

        //大于7
        Predicate<Integer> greater7 = new Predicate<Integer>() {
            public boolean apply(Integer input) {
                return input > 7;
            }
        };
        System.out.println(greater7.apply(2)); //输出:false
        System.out.println(greater7.apply(8)); //输出:true

        //小于3
        Predicate<Integer> less3 = new Predicate<Integer>() {
            public boolean apply(Integer input) {
                return input < 3;
            }
        };
        System.out.println(less3.apply(2));//输出:true
        System.out.println(less3.apply(8));//输出:false

        //大于7或小于3
        Predicate<Integer> or = Predicates.or(greater7, less3);
        System.out.println(or.apply(2));//输出:true
        System.out.println(or.apply(8));//输出:true

compose

Predicate pre=Predicates.compose(Predicate,Function);

组合一个predicate和function,形成新的predicate,实际执行apply时候的过程如下所示:先用Function转换下入参a,然后应用到predicate

    public boolean apply(A a) {
      return predicate.apply(function.apply(a));
    }

Supplier

Supplier是一个接口,用来帮助我们创建对象实例。借助Supplier可以实现创建型的设计模式,get方法抽象了创建对象的细节。源码如下:

public interface Supplier<T> {
  T get();
}

具体用的时候就是实现Supplier接口实现自己的逻辑,这个接口是不是感觉没太大用途,除了在抽象的语义方面。如果结合Suppliers就能看出来用途了。

Suppliers

提供了处理Supplier的一些操作
memoize
可以实现单例,使用方法如下:

       //定义一个Supplier,里面创建对象
        Supplier<String> supp = new Supplier<String>() {
            public String get() {
                System.out.println("初始化对象。。。");
                return "guava";
            }
        };
        //得到一个创建单例对象的Supplier
        Supplier<String> memoize = Suppliers.memoize(supp);
        System.out.println(memoize.get());
        System.out.println(memoize.get());

执行结果如下,调用了两次get,但只执行了一次对象初始化

初始化对象。。。
guava
guava

查看memoize的源码,可以看到使用的是双重校验加锁创建单例的方式:

    public T get() {
      // A 2-field variant of Double Checked Locking.
      if (!initialized) {
        synchronized (this) {
          if (!initialized) {
            T t = delegate.get();
            value = t;
            initialized = true;
            return t;
          }
        }
      }
      return value;
    }

顺便提下java实现单例的有几种方式:

  • 饿汉模式的声明初始化
private static final Type instance=new Type();
  • 双重校验加锁
private volatile Type instance;

public static Type getInstance(){
    if(instance==null){
        synchronized (Type.class){
            if(instance==null){
                instance=new Type();
            }
        }
    }
    return instance;
}
  • 内部类
   public class Type{   

        private static class SingletonHelper{
            private static final Type INSTANCE = new Type ();
        }

        public static Type getInstance(){
            return SingletonHelper.INSTANCE;
        }
    }
  • 枚举
public enum EnumSingleton {

    //some 属性

    INSTANCE;

    public static void doSomething(){
        //do something
    }
}

memoizeWithExpiration
提供了获取单例功能的同时增加了超时失效重新获取的功能呢。Suppliers.memoizeWithExpiration(Supplier supplier,long duration,TimeUnit timenunit)
实例如下:

        Supplier<Object> supp = new Supplier<Object>() {
            public Object get() {
                System.out.println("初始化对象。。。");
                return new Object();
            }
        };
        Supplier<Object> memoize = Suppliers.memoizeWithExpiration(supp,3, TimeUnit.SECONDS);
        System.out.println(memoize.get());
        System.out.println(memoize.get()); //未超时,不用重新初始化对象
        TimeUnit.SECONDS.sleep(4); //这里会有异常在方法上声明了
        System.out.println(memoize.get()); //超时重新初始化对象

从输出结果可以看到,超时后又重新初始化了一个新的对象

初始化对象。。。
java.lang.Object@19b49e6
java.lang.Object@19b49e6
初始化对象。。。
java.lang.Object@6ca1c
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值