【问题标题】:how to do filter/query on in-memory list/map using guava如何使用番石榴对内存列表/映射进行过滤/查询
【发布时间】:2012-03-01 16:31:09
【问题描述】:

我有复杂的对象

    class Person{
        Integer id;
        String fname;
        String lname;
        //..... there are more attributes
        List<Address> addresses;
    }
    class Address{
        String street1;
        String street2;
        String city;
        String state;
        String zip;
    }

我有大约 30000 个人 个对象,每个对象至少有 200-500 个子对象(地址)。现在我拥有所有这些内存,并且我有不同的场景(20-30 个场景),我必须根据场景中可用的过滤器查询/过滤对象。例如。

  • scen1 -> 获取所有具有 lname = 'zoik' 的对象
  • scen2 -> 获取所有具有 lname = 'smark' 和 address.street1 = "xyz" 的对象
  • scen3 -> 获取所有具有 lname = 'smark' 和 address.street1 = "xyz" 和 address.street1 = "pqr" 的对象(记住每个对象都有多个地址,所以我需要两个地址都满足上述条件的对象.)
  • scen4 -> 获取所有具有 fname= "smith" 和 lname = 'smark' 和 address.city="Los Angeles" 的对象
  • .....

简而言之,两个对象的不同组合有多种场景。 请建议在这种情况下使用番石榴的最佳方法?

【问题讨论】:

    标签: java collections guava


    【解决方案1】:

    您应该将Iterables.filter(Iterable, Predicate)Predicates 结合使用。

    例子:

    public class PersonLastNameEqualsPredicate implements Predicate<Person> {
      private String personName;
      public PersonNameEqualsPredicate (String personName) {this.personName= personName;}
      public boolean apply(Person p) { return this.personName.equals(p.getLName()); }
    }
    
    public class PersonStreet1EqualsPredicate implements Predicate<Person> {
      private String street1Name;
      public PersonStreet1EqualsPredicate (String street1Name) {this.street1Name = street1Name;}
      public boolean apply(Person p) {
        for (Address a: p.getAddresses()) {
          if (street1Name.equals(a.getStreet1()) return true;
        }
        return false;
      }
    }
    
    // Extra predicates as you need them
    

    每个场景项需要一个谓词。然后你需要根据需要对它们进行调制:

    1.

    Predicate<Person> peopleNamedZoik = new PersonLastNamePredicate("zoik");
    

    2.

    Predicate<Person> peopleNamedSmarkAndLivingInXyzStreet = Predicates.and(new PersonLastNamePredicate("smark"), new PersonStreet1EqualsPredicate("xyz"));
    

    3.

    在这里,您应该调整您的街道谓词以立即检查所有街道名称是否包含您的所有期望。

    那么这只是一个问题

    1.

    List<Person> myLongPersonList = ...;
    Iterable<Person> zoikPeople = Iterables.filter(myLongPersonList, peopleNamedZoik);
    

    2.

    List<Person> myLongPersonList = ...;
    Iterable<Person> zoikPeople = Iterables.filter(myLongPersonList, peopleNamedSmarkAndLivingInXyzStreet);
    

    等等。

    【讨论】:

    • 感谢您的回复。只有一个问题,在应用谓词时,我不想每次应用谓词时都迭代到 30K 对象。有什么方法可以在第一次迭代时构建地图/索引,然后在处理它们时查询这些对象?类似于第 1 步:构建索引或地图第 2 步:myFilteredObjects = someListOrMap.get(scenarioDef) 我对 Guava 不太熟悉,所以可能对它有很多期望:D,请随时纠正我。非常感谢。
    • 过早优化?你确定你在乎吗? 30000 并不是很多迭代,特别是如果它们已经在内存中
    • @rst:你得到了一个惰性迭代器,所以在那一刻实际上还没有任何迭代。然后,您可以使用其他临时集合来实际迭代和存储它们。最好使用 guava 的静态构造函数,例如 Lists.newArrayList(Iterable),因为它们支持获取可迭代对象。
    • 你为什么不构建一个复杂的谓词?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-24
    • 1970-01-01
    • 1970-01-01
    • 2012-04-27
    相关资源
    最近更新 更多