【问题标题】:Fastest way to search for an object in a list in java在java中的列表中搜索对象的最快方法
【发布时间】:2017-03-17 10:52:47
【问题描述】:

我有一个结构:

public class DataItem {
    public int wordID, categoryID, documentID, count;
}

我有一个如下列表:

final public ArrayList<DataItem> data = new ArrayList<>();

我已经写了一个在里面搜索的方法:

public DataItem FindDataItem(final int wordID, final int categoryID, final int documentID)
{
    for(DataItem dataItem : data)
        if(dataItem.wordID == wordID && dataItem.documentID == documentID && dataItem.categoryID == categoryID)
            return dataItem;
    return null;
}

但是太慢了。如何加快速度?

我正在考虑四个 HashMap 相互内部,但我想像数据库表一样使用这些数据,因此很难在 HashMap 中按计数分组

我也在考虑ParalellStream,但是不知道怎么用。看起来很复杂。但它仍然是 O(n)。

我也在考虑使用数据库。但我不想有 IO。我希望它全部在 RAM 中。

请指导我完成这个。

【问题讨论】:

  • I am thinking about using a database too. But I don't want to have IO. I want it all inside RAM. 然后你可以使用 SQLite,它是 DB-on-file,用法与任何其他 db 相同,除非你在客户端和服务器之间没有任何真正的连接。
  • @BackSlash 有 IO。
  • 最好是 HashMap 因为 get(object) 可以在恒定时间内找到...
  • OP 数组可以包含多个具有相同值的数据项。她的 find 算法只返回第一个。如果您使用的是基于 dataItem 值的哈希映射,则不允许重复。被丢弃。

标签: java search parallel-processing hashmap


【解决方案1】:

正如@ShreyasSarvothama 在 cmets 中所说,检索值的最快方法是使用 Map。

我认为您可以使用一个映射,其键是使用您用作 find 方法参数的值计算的(考虑到它们的组合给出了 DataItem 的唯一标识符)。

import java.util.*;
import java.util.stream.*;

public class Test {

    private class DataItem {
        public int wordID, categoryID, documentID, count;

        public DataItem(int w, int c, int d) {
            wordID = w;
            categoryID = c;
            documentID = d;
        }

        public String toString() {
            return "wordID:" + wordID + " categoryID:" + categoryID + " documentID:" + documentID;
        }
    }

    private Map<Integer, DataItem> map;

    public void setList(List<DataItem> list) {
        this.map = list.stream().collect(Collectors.toMap(dataItem -> dataItem.wordID * dataItem.categoryID * dataItem.documentID, dataItem -> dataItem));        
    }

    public DataItem getDataItem(int wordID, int categoryID, int documentID) {
        return map.get(wordID * categoryID * documentID);
    }

    public static void main(String[] args) {
        Test t = new Test();
        t.setList(Arrays.asList(t.new DataItem(1,2,3), t.new DataItem(2,3,4), t.new DataItem(3,3,4)));
        System.out.println(t.getDataItem(2,3,4));
    }
}

希望对你有帮助。

【讨论】:

    【解决方案2】:

    以下是使用并行流的方法:

    public DataItem FindDataItem(final int wordID, final int categoryID, final int documentID) {
        return data.parallelStream()
                .filter(dataItem -> dataItem.wordID == wordID
                        && dataItem.documentID == documentID
                        && dataItem.categoryID == categoryID)
                .findAny()
                .orElse(null);
    }
    

    正如你所说,它不会影响时间复杂度,但它可以根据可用线程的数量加快操作。

    【讨论】:

    • 请在这里澄清一下,Hashmap get() 不是在恒定时间内返回的。paralleStream 是否也在恒定时间内返回?
    • @ShreyasSarvothama 我的理解是 OP 希望能够通过键的子集(例如 (wordID, documentID))进行查询,而 HashMap 不能很好地扩展。
    猜你喜欢
    • 2011-08-25
    • 2014-10-03
    • 2012-05-23
    • 2011-03-05
    • 2012-03-11
    • 2016-04-03
    • 2012-08-05
    • 2011-07-08
    • 1970-01-01
    相关资源
    最近更新 更多