Google Guava - 在单个属性上过滤多个输入

时间:2015-01-08 23:16:50

标签: collections filter guava android-guava

我刚进入谷歌番石榴,它似乎是一个强大的工具,我看到你如何使用Predicates和特定属性过滤。如何在FluentIterable中链接谓词我的问题是过滤单个属性的最佳方式。

例如,如果我有一系列汽车。如何过滤Cars.getPaintColor()给我黑色,红色和黄色的车?创建3个单独的谓词并使用FluentIterable似乎很笨拙。特别是在我的使用中,我可能希望在同一个属性上有10个以上的过滤器,我不想创建10个谓词。

谢谢!

        List<String> colorList = (List<String>)filterCriteria.get("Color");
        List<String> makeList = (List<String>)filterCriteria.get("Make");
        List<String> rimSizeList = (List<String>)filterCriteria.get("RimSize");

        Predicate<String> predColor = Predicates.in(ImmutableSet.copyOf(colorList));
        Predicate<CarObj> predDirection2 = Predicates.compose(predColor ,[????] );

        Predicate<String> predMakeList  = Predicates.in(ImmutableSet.copyOf(makeList));
        Predicate<CarObj> predMakeList2 = Predicates.compose(predMakeList, [????] );

        Predicate<String> predRimSize = Predicates.in(ImmutableSet.copyOf(rimSizeList));
        Predicate<CarObj> predRimSize2 = Predicates.compose(predRimSize, [????] );

        Collection<CarObj> filtered = FluentIterable.from(mAllCars)
                .filter(predDirection2)
                .filter(predMakeList2)
                .filter(predRimSize2)
                .toList();

由于我使用的是List,因此在创建ImmutableSet时使用了copyOf而不是of

我不确定要在compose的第二个参数中添加什么。我猜这是类似的......在CarObj课程中。

static Predicate<CarObj> byColor= new Predicate<CarObj>() {
    public boolean apply(CarObj input) {

        // What do I put here?
    }
};

2 个答案:

答案 0 :(得分:3)

因此,要检查颜色是黑色,读取还是黄色,您需要创建一个Predicate来检查一组是否包含该颜色:

Predicate<PaintColor> p = Predicates.in(ImmutableSet.of(
    PaintColor.RED, PaintColor.BLACK, PaintColor.YELLOW));

然后,您可以使用Function<Car, PaintColor>来复制该类,以返回类的paint颜色属性:

Predicate<Car> p2 = Predicates.compose(p, Car.GET_PAINT_COLOR_FUNCTION);

修改

Car.GET_PAINT_COLOR_FUNCTION我的意思是:

public static final Function<Car, PaintColor> GET_PAINT_COLOR_FUNCTION =
    new Function<Car, PaintColor>() {
      @Override public PaintColor apply(Car car) {
        return car.getPaintColor();
      }
    });

正如我在评论中所说,您可以根据需要将其调整为您的实际类型。例如,改为Function<CarObj, String>

答案 1 :(得分:2)

根据ColinD的建议,使用Function<Car, PaintColor>撰写提取Predicates.in()的替代方法是编写参数化Predicate<Car>

public class CarPaintColorPredicate implements Predicate<Car> {
    private final PaintColor paintColor;

    public CarPaintColorPredicate(PaintColor paintColor) {
        this.paintColor = paintColor;
    }

    @Override
    public boolean apply(@Nullable Car input) {
        return input != null && input.getPaintColor() == paintColor;
    }
}

然后您可以直接使用:

FluentIterable.from(cars)
        .filter(new CarPaintColorPredicate(PaintColor.RED))
        .toList();

或组合多种颜色:

FluentIterable.from(cars)
        .filter(Predicates.or(
            new CarPaintColorPredicate(PaintColor.RED),
            new CarPaintColorPredicate(PaintColor.BLACK)))
        .toList();

甚至与其他类型的谓词结合使用:

FluentIterable.from(cars)
        .filter(new CarPaintColorPredicate(PaintColor.RED))
        .filter(new CarMakePredicate("Ferrari"))
        .toList();

要完成,Function<Car, PaintColor>的版本如下:

public enum CarPaintColorFunction implements Function<Car, PaintColor> {
    INSTANCE;

    @Override
    public PaintColor apply(@Nullable Car input) {
        return input == null ? null : input.getPaintColor();
    }
}

Function只返回属性的值,然后通过Set组合将其与可接受值的集合(希望是Predicate)进行比较:

FluentIterable.from(cars)
        .filter(Predicates.compose(
            Predicates.in(Sets.immutableEnumSet(PaintColor.RED, PaintColor.BLACK)),
            CarPaintColorFunction.INSTANCE))
        .toList();

所有这些都在Guava Wiki的Functional Explained页面中得到了解释。