【问题标题】:Google Guava - Filter Multiple Inputs on Single PropertyGoogle Guava - 过滤单个属性的多个输入
【发布时间】:2015-01-08 23:16:49
【问题描述】:

我刚进入 Google Guava,它似乎是一个强大的工具,我了解了如何使用谓词并按特定属性进行过滤。如何在FluentIterable 中链接谓词我的问题是过滤单个属性的最佳方法是什么。

例如,如果我有一个 Cars 集合。如何过滤 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?
    }
};

【问题讨论】:

  • 您想一次过滤属性的一个值(但使用不同的可能值),还是想根据属性值对所有汽车进行分区?您要么需要参数化的 Predicate,要么只需要提取 Function(如 ColinD 所述)和 Multimaps.index()
  • @FrankPavageau 我想过滤具有不同可能值的属性的一个值,但我也想过滤具有不同可能值的其他属性。

标签: collections filter guava android-guava


【解决方案1】:

因此,要检查油漆颜色是黑色、浅色还是黄色之一,您需要创建一个 Predicate 来检查集合是否包含该颜色:

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

然后您可以使用 Function&lt;Car, PaintColor&gt; 来组合它,它返回您的类的油漆颜色属性:

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();
      }
    });

正如我在 cmets 中所说,您可以根据需要将其调整为您的实际类型。例如,改为 Function&lt;CarObj, String&gt;

【讨论】:

  • @Alan:从那里你只需将谓词传递给filter
  • 如果颜色不是枚举怎么办?
  • @Alan:如何创建传递给Predicates.inCollection 并不重要。
  • 但我看到你有Predicate&lt;PaintColor&gt;。这是否意味着我需要用一个保存油漆颜色的字符串来创建一个类?以及它的getter/setter?
  • PaintColor 替换为您碰巧代表油漆颜色的任何类型。如果是String,则将其设为Predicate&lt;String&gt;。我使用了PaintColor,因为我认为它让我的例子更清楚。
【解决方案2】:

按照 ColinD 的建议,将提取的 Function&lt;Car, PaintColor&gt;Predicates.in() 组合在一起的替代方法是编写参数化的 Predicate&lt;Car&gt;

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&lt;Car, PaintColor&gt;的版本如下:

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

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

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

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

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

【讨论】:

  • 谢谢你,弗兰克,你能举例说明Function&lt;Car, PaintColor&gt;Predicates.in() 是如何工作的吗?
  • 还有一个例子。
猜你喜欢
  • 2021-03-17
  • 2016-05-11
  • 2020-04-27
  • 2015-03-11
  • 2011-02-05
  • 1970-01-01
  • 1970-01-01
  • 2019-05-18
  • 1970-01-01
相关资源
最近更新 更多