这写API可解决的问题

1. 集合元素的过滤 - FluentIterable Predicate Range Function

1) 先说Predicate<T>,这个相当与一个过滤原则,里面有个apply()方法,通过一定的条件返回true或false,依次判断元素需不需要过滤

其中T表示待过滤集合里面的元素类型,举个例子

package guavaexam.test;

public class Man {
    private String name;
    private int age;

    public Man(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return name + " is " + age + " years old";
    }
}

package guavaexam.test;

import com.google.common.base.Predicate;

public class AgePredicate implements Predicate<Man> {
    private int minAge;

    public AgePredicate(int minAge) {
        this.minAge = minAge;
    }

    @Override
    public boolean apply(Man man) {
        if (man.getAge() < minAge)
            return false;
        return true;
    }
}

package guavaexam.test;

import com.google.common.base.Predicate;

public class NamePredicate implements Predicate<Man> {
    private String illegalName;

    public NamePredicate(String illegalName) {
        this.illegalName = illegalName;
    }

    @Override
    public boolean apply(Man man) {
        if (man.getName().contains(illegalName))
            return false;
        return true;
    }
}

 

此处predicate的作用是用来过滤age小于minAge的人,运用Predicates.and(predicate1, predicate2)或者Predicates.or(x,x)方法,我们可以组合多个predicate过滤器,形成一个复杂的组合条件来过滤集合元素

 

2) 再来说Function<E, T>,这个类主要使用来转换集合元素,其中有个apply方法,将 E 类型的元素转为 T 类型的元素返回,一般我们可以写在一个匿名类里用,例如

        Iterable<Man> manIterable = FluentIterable.from(manList).filter(predicate).limit(2)
                .transform(new Function<Man, Man>() {
                    @Override
                    public Man apply(Man man) {
                        man.setAge(man.getAge() * 2);
                        return man;
                    }
                });

这个例子表示的就是将集合里的每个Man的年龄乘以2再返回

3) FluentIterable,这个类可以配合Predicate和Function对集合的每个元素进行自定义过滤,他们的配合就类似与Collections.sort()和Comparator的组合,查看如下完整的例子

package guavaexam.test;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;

import java.util.List;

public class FluentIterableTest {
    public static void main(String[] args) {
        Man man1 = new Man("Jack Miller", 18);
        Man man2 = new Man("Roy Miller", 18);
        Man man3 = new Man("Lily Miller", 11);
        Man man4 = new Man("Rose Miller", 5);
        Man man5 = new Man("Mike Chen", 34);

        List<Man> manList = ImmutableList.of(man1, man2, man3, man4, man5);

        // 组合Predicate条件
        Predicate<Man> predicate = Predicates.alwaysTrue();
        predicate = Predicates.and(predicate, new NamePredicate("Chen"));
        predicate = Predicates.and(predicate, new AgePredicate(15));

        // 使用FluentIterable过滤元素,返回一个Iterable[]
        Iterable<Man> manIterable = FluentIterable.from(manList).filter(predicate).limit(2)
                .transform(new Function<Man, Man>() {
                    @Override
                    public Man apply(Man man) {
                        man.setAge(man.getAge() * 2);
                        return man;
                    }
                });

        System.out.println(manIterable);
    }
}

结果输出

[Jack Miller is 36 years old, Roy Miller is 36 years old]

2. 集合元素的排序

Ordering类用来构建复杂比较器,其中几个方法如下:

from(): 第一个使用的比较器,第一顺序

compound(): 第二个使用的比较器,第二顺序

onResultOf(Function func): 在两个元素比较之前,先用Function转换这个两个元素,注意是在两个元素比较之前,而不是在所有元素比较之前,下面可以看到效果

看下面的例子

package guavaexam.test.ordering;

import guavaexam.test.model.Man;

import java.util.Comparator;

public class NameComparator implements Comparator<Man> {
    @Override
    public int compare(Man man, Man man1) {
        return man.getName().compareTo(man1.getName());
    }
}


package guavaexam.test.ordering;

import guavaexam.test.model.Man;

import java.util.Comparator;

public class AgeComparator implements Comparator<Man> {
    @Override
    public int compare(Man man, Man man1) {
        return man.getAge() > man1.getAge() ? 1 : (man.getAge() == man1.getAge() ? 0 : -1);
    }
}


package guavaexam.test.ordering;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import guavaexam.test.model.Man;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class OrderingTest {
    public static void main(String[] args) {
        Man man1 = new Man("Jack Miller", 18);
        Man man2 = new Man("Roy Miller", 18);
        Man man3 = new Man("Lily Miller", 11);
        Man man4 = new Man("Rose Miller", 5);
        Man man5 = new Man("Mike Chen", 34);

        List<Man> manList = Lists.newArrayList(man1, man2, man3, man4, man5);

        Comparator<Man> manComparator = Ordering
                .from(new AgeComparator()).compound(new NameComparator())
                .reverse()
                .onResultOf(new Function<Man, Man>() {
                    @Override
                    public Man apply(Man man) {
                        man.setAge(man.getAge() * 2);
                        return man;
                    }
                });

        Collections.sort(manList, manComparator);

        System.out.println(manList);
    }
}

这个输出会非常诡异

[Roy Miller is 72 years old, Jack Miller is 144 years old, Lily Miller is 176 years old, Mike Chen is 136 years old, Rose Miller is 40 years old]

可以看到年龄并非只是 * 2,而是不可预见的被 * 2 了多次,这是因为当元素A在与元素B比较的时候就会被执行一次Function,当元素A与元素C比较时又会执行一次Function,所以最后你并不知道被执行了多少次

 

3. 范围判断 - Range

比较简单,不多做介绍了

package guavaexam.test.range;

import com.google.common.collect.Range;

public class RangeTest {
    public static void main(String[] args) {
        // 一个左开右闭的范围    
        Range<Integer> range = Range.openClosed(5, 10);
        System.out.println(range.contains(1));
        System.out.println(range.contains(6));
        System.out.println(range.contains(9));
        System.out.println(range.contains(10));
    }
}

输出

false
true
true
true

 

4. Splitter 字符串切割

其常用方法有如下几个

on(String sep): 按照sep切分字符串

trimResults(): 去掉切分结果的首尾空格

omitEmptyStrings(): 忽略切分出来的空结果

withKeyValueSeparator(String sep): 根据sep在字符串切割后再切割结果变成一个map

例子如下

package guavaexam.test.splitter;

import com.google.common.base.Splitter;

import java.util.Map;

public class SplitterTest {
    public static void main(String[] args) {
        String s = " name $ jack?age$ 17 ?  $ook ?";
        Iterable<String> list = Splitter.on("?").trimResults().omitEmptyStrings().split(s);
        System.out.println(list);
        Map<String, String> list2 = Splitter.on("?").trimResults().omitEmptyStrings().withKeyValueSeparator("$").split(s);
        System.out.println(list2);
    }
}

[name $ jack, age$ 17, $ook]
{name = jack, age= 17, =ook}

 

posted on 2013-07-12 01:01  ZimZz  阅读(2551)  评论(0编辑  收藏  举报