【问题标题】:object search optimization in memory内存中的对象搜索优化
【发布时间】:2013-11-05 23:54:10
【问题描述】:

我有一个 MyObjects 的 ArrayList。 MyObjects 类有 10 多个属性,但我只需要从 4 个属性中搜索。用户将按下按钮并能够选择property1 的值。 假设用户将选择property1Value1property1Value2property1Value4,然后他将按下按钮并选择property2 值:property2Value1property2Value5、property2Value7 等等。这些是filter1和filter2。 property2Value2property2Value3property2Value4 对用户不可见,因为他使用 filter1 过滤掉了。就像在他进入新的过滤屏幕之前进行搜索一样。 我需要将他在每个过滤器中选择的内容存储在某个地方,因为当他返回导航时,我必须向他显示所选值。

我认为用图片更容易理解,因为在 ebay 上实现了类似的功能:

一开始没有过滤器:用户可以选择每个属性的所有值:

用户选择“平板电脑”作为类型属性。 - 搜索完成,一些属性值不再可见:

第二个过滤值被选中:

按下(自动)搜索我应该在 SQL 中做这样的事情:

SELECT * FROM MyObjects WHERE
( (property1  = property1Value1) || (property1  = property1Value2) || (property1  = property1Value4) )
AND
(  (property2 = property2Value1) ||  (property2 = property2Value5) )

由于我在内存中有对象,我认为创建 sqlLite3 数据库不是一个好主意,写出来而不是选择。在 iOS 实现中,我做了非常复杂的缓存算法。缓存分离的过滤器值。一大堆辅助索引持有者(最少 20 个),因为对于每个过滤器,我都需要做一些额外的事情,这里没有提到,并且数据只存储一次。

我害怕将该算法重写到 Android,iOS 上的算法一定很简单。

编辑: 基本上我需要在 Java 对象搜索中重写那个 SQL 搜索。

编辑2: 基于 Multimap 的回答。

Multimap 并不比HashMap<String, <ArrarList<Integer>> 好 其中键是属性值 (property2Value3),值是我的 ArrayList<MyObjects> (1,2,3,4,5...100) 的索引列表

需要在每个过滤器上建立,每个过滤器值HashMap<String, <ArrarList<Integer>> 而不是我在那里,iOS...可能少了一些辅助集合。

有什么想法吗?

【问题讨论】:

  • A Multimap is 如果您已经将对象保存在内存中,则比映射到 ID 字段更好;你没有包装类的开销,你不必手动查找对象,你可以直接执行Collection操作。 Multimap 几乎完全等同于 Map<Key,Set<Value>>,但有一些额外的便利方法。

标签: java android search optimization collections


【解决方案1】:

MYSQL 是如何在后台执行 SQL 的? - 在 MyISAM 表有一个文件,他有数据,在其他文件有 id 位置。

SELECT * FROM mytable 会将所有 ID 放入结果集中,因为没有过滤器。 因为是*会将所有字段复制到id。这相当于:

ArrayList<MyObject> result = new ArrayList<MyObject>();
for(int i=0; i < listMyObjects.size(); i++){
    if(true == true){// SELECT * FROM has a hidden WHERE 1, which is always true
      result.add(listMyObjects.get(i));
    }
}

如果是过滤器,它应该有一个过滤器列表:

ArrayList<String> filterByProperty1 = new ArrayList<String> ();

在过滤器界面我会添加一些字符串property1Value1,property1Value2....搜索算法是:

    ArrayList<MyObject> result = new ArrayList<MyObject>();
    for(int i=0; i < listMyObjects.size(); i++){
          MyObject curMyObject = listMyObjects.get(i);
          // lets see if bypass the filter, if filter exists  
          boolean property1Allow = false;
          boolean property2Allow = false;
          if(filterByProperty1.size() > 0){
              String theCurProperty1Value = curMyObject.getProperty1();
               if(filterByProperty1.contains(theCurPropertyValue)){
                   property1Allow = true;
               }
           }
           else{// no filter by property1: allowed to add to result
               property1Allow = true;
           }

          // do the same with property2,3,4, lazzy to write it

           if(property1Allow && property2Allow){
              result.add(theCurPropertyValue);
           }
        }
    }

不确定这是否会慢很多,但我至少已经从第十/一百个辅助集合、索引中逃脱了。在此之后,我将制作所需的额外内容并完成

【讨论】:

  • 这看起来像是为了获得未经证实的性能优势而进行的大量容易出错的工作。我建议尝试更简单的过滤机制,然后仅在您能指出减速的确切位置时手动尝试。
【解决方案2】:

您所说的基本上是索引。与您描述的类似的方法在 Java 中是完全可以管理的,它只需要与在 Objective C 中相同的仔细编码。

您没有详细说明诸如是否允许多个项目在其字段中具有相同值的问题,所以我假设它们是。在这种情况下,我会这样开始:

  • 使用 Guava 的 Multimap,可能是 HashMultimap,其中键是被索引的属性,每个被索引的对象都会在该键下的映射中获得 put
  • 当您尝试搜索多个字段时,调用multimap.get(property) 以获取与该属性匹配的所有对象的Collection,并仅保留与所有属性匹配的对象:

    Set<Item> items = new Set<Items>(typeMultimap.get("tablet"));
    items.retainAll(productLineMultimap.get("Galaxy Tab"));
    // your results are now in "items"
    
  • 如果您的属性列表稳定,请编写一个包装器 Indexer 类,其中包含所有 Multimaps 的字段,并确保将对象插入到所有属性索引中并从中删除,并且可能具有方便的包装器地图吸气剂。

【讨论】:

  • +1 谢谢,我会检查 Multimap,以前从未使用过。将问题编辑得更清楚:我需要重写该 SQL 以在 Collection 中搜索。究竟 ebay 如何使用 sql
  • 你觉得我的解决方案怎么样?
猜你喜欢
  • 2014-11-20
  • 2019-05-18
  • 2015-07-30
  • 1970-01-01
  • 1970-01-01
  • 2014-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多