使用Guava索引可以匹配多属性的字段
Using Guava to index fields that can match multi properties
我们有一组计划要根据 3 个属性编制索引。每个值都可以有任何值的组合,到目前为止,它们只能是 3 个中的 1 个。我们希望能够使用 Guava,因为这是公司的代码标准,因此我需要尽我最大的努力将它用于任何循环。 Products 集合可能非常大,因此我们希望尽可能减少循环数量。这是我们拥有的:
private static Function<Product, ProductType> TO_PRODUCT_TYPE =
new Function<Product, ProductType>()
{
@Override
public ProductType apply(Product product)
{
if (product.isOne())
{
return ProductType.ONE;
}
else if (product.isTwo())
{
return ProductType.TWO;
}
else if (product.isThree())
{
return ProductType.THREE;
}
return null;
};
}
...
Multimap<ProductType, Product> productsByType = Multimaps.index(products, TO_PRODUCT_TYPE);
List<Product> oneProducts = (List<Product>) productsByType.get(SINGLE);
List<Product> twoProducts = (List<Product>) productsByType.get(ProductType.TWO);
List<Product> threeProducts = (List<Product>) productsByType.get(ProductType.THREE);
但是,如果每种类型只有一种,这也是可行的。如果有多种可能性,有没有办法索引?例如,如果 Product 1 既是 ONE 又是 TWO,那么它将同时出现在 oneProducts 和 twoProducts 中。
ImmutableListMultimap.Builder<ProductType, Product> builder =
ImmutableListMultimap.builder();
for (Product product : products) {
if (product.isOne()) {
builder.put(ProductType.ONE, product);
}
if (builder.isTwo()) {
builder.put(ProductType.TWO, product);
}
// ...
// or better, if possible:
for (ProductType type : product.getTypes()) {
builder.put(type, product);
}
}
ImmutableListMultimap<ProductType, Product> productsByType = builder.build();
Guava 目前未提供此功能,但您可以随时复制 Multimaps.index(...)
并创建自己的 multiIndex(...)
:
public static <K, V> ImmutableListMultimap<K, V> multiIndex(
Iterable<V> values, Function<? super V, ? extends Iterable<? extends K>> keysFunction) {
return multiIndex(values.iterator(), keysFunction);
}
public static <K, V> ImmutableListMultimap<K, V> multiIndex(
Iterator<V> values, Function<? super V, ? extends Iterable<? extends K>> keysFunction) {
checkNotNull(keysFunction);
ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
while (values.hasNext()) {
V value = values.next();
checkNotNull(value, values);
Iterable<? extends K> keys = keysFunction.apply(value);
checkNotNull(keys, value);
for (K key : keys) {
builder.put(key, value);
}
}
return builder.build();
}
然后您可以通过将 TO_PRODUCT_TYPE
更新为 TO_PRODUCT_TYPES
:
来使用它
private static Function<Product, EnumSet<ProductType>> TO_PRODUCT_TYPES =
new Function<Product, EnumSet<ProductType>>() {
@Override
public EnumSet<ProductType> apply(Product product) {
EnumSet<ProductType> productTypes = EnumSet.noneOf(ProductType.class);
if (product.isOne()) {
productTypes.add(ProductType.ONE);
}
if (product.isTwo()) {
productTypes.add(ProductType.TWO);
}
if (product.isThree()) {
productTypes.add(ProductType.THREE);
}
return productTypes;
}
};
...
Multimap<ProductType, Product> productsByType = multiIndex(products, TO_PRODUCT_TYPES);
List<Product> oneProducts = (List<Product>) productsByType.get(ProductType.ONE);
List<Product> twoProducts = (List<Product>) productsByType.get(ProductType.TWO);
List<Product> threeProducts = (List<Product>) productsByType.get(ProductType.THREE);
请注意,这将忽略没有类型的产品。
我们有一组计划要根据 3 个属性编制索引。每个值都可以有任何值的组合,到目前为止,它们只能是 3 个中的 1 个。我们希望能够使用 Guava,因为这是公司的代码标准,因此我需要尽我最大的努力将它用于任何循环。 Products 集合可能非常大,因此我们希望尽可能减少循环数量。这是我们拥有的:
private static Function<Product, ProductType> TO_PRODUCT_TYPE =
new Function<Product, ProductType>()
{
@Override
public ProductType apply(Product product)
{
if (product.isOne())
{
return ProductType.ONE;
}
else if (product.isTwo())
{
return ProductType.TWO;
}
else if (product.isThree())
{
return ProductType.THREE;
}
return null;
};
}
...
Multimap<ProductType, Product> productsByType = Multimaps.index(products, TO_PRODUCT_TYPE);
List<Product> oneProducts = (List<Product>) productsByType.get(SINGLE);
List<Product> twoProducts = (List<Product>) productsByType.get(ProductType.TWO);
List<Product> threeProducts = (List<Product>) productsByType.get(ProductType.THREE);
但是,如果每种类型只有一种,这也是可行的。如果有多种可能性,有没有办法索引?例如,如果 Product 1 既是 ONE 又是 TWO,那么它将同时出现在 oneProducts 和 twoProducts 中。
ImmutableListMultimap.Builder<ProductType, Product> builder =
ImmutableListMultimap.builder();
for (Product product : products) {
if (product.isOne()) {
builder.put(ProductType.ONE, product);
}
if (builder.isTwo()) {
builder.put(ProductType.TWO, product);
}
// ...
// or better, if possible:
for (ProductType type : product.getTypes()) {
builder.put(type, product);
}
}
ImmutableListMultimap<ProductType, Product> productsByType = builder.build();
Guava 目前未提供此功能,但您可以随时复制 Multimaps.index(...)
并创建自己的 multiIndex(...)
:
public static <K, V> ImmutableListMultimap<K, V> multiIndex(
Iterable<V> values, Function<? super V, ? extends Iterable<? extends K>> keysFunction) {
return multiIndex(values.iterator(), keysFunction);
}
public static <K, V> ImmutableListMultimap<K, V> multiIndex(
Iterator<V> values, Function<? super V, ? extends Iterable<? extends K>> keysFunction) {
checkNotNull(keysFunction);
ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
while (values.hasNext()) {
V value = values.next();
checkNotNull(value, values);
Iterable<? extends K> keys = keysFunction.apply(value);
checkNotNull(keys, value);
for (K key : keys) {
builder.put(key, value);
}
}
return builder.build();
}
然后您可以通过将 TO_PRODUCT_TYPE
更新为 TO_PRODUCT_TYPES
:
private static Function<Product, EnumSet<ProductType>> TO_PRODUCT_TYPES =
new Function<Product, EnumSet<ProductType>>() {
@Override
public EnumSet<ProductType> apply(Product product) {
EnumSet<ProductType> productTypes = EnumSet.noneOf(ProductType.class);
if (product.isOne()) {
productTypes.add(ProductType.ONE);
}
if (product.isTwo()) {
productTypes.add(ProductType.TWO);
}
if (product.isThree()) {
productTypes.add(ProductType.THREE);
}
return productTypes;
}
};
...
Multimap<ProductType, Product> productsByType = multiIndex(products, TO_PRODUCT_TYPES);
List<Product> oneProducts = (List<Product>) productsByType.get(ProductType.ONE);
List<Product> twoProducts = (List<Product>) productsByType.get(ProductType.TWO);
List<Product> threeProducts = (List<Product>) productsByType.get(ProductType.THREE);
请注意,这将忽略没有类型的产品。