Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fastest way to search for an object in a list in java

I have a structure:

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

I have a list of it like below:

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

I have written a method to search inside it:

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

But it is so slow. How can I speed it up?

I am thinking of four HashMaps inside each other but I want to use this data like a database table so it is hard to do group by count in HashMap

I am also thinking about ParalellStream but I don't know how to use it. Looks complicated. but it is still O(n).

I am thinking about using a database too. But I don't want to have IO. I want it all inside RAM.

Please guide me through this.

like image 464
Matin Lotfaliee Avatar asked Oct 29 '22 17:10

Matin Lotfaliee


1 Answers

As @ShreyasSarvothama says in the comments, the fastest way to retrieve values would be using a Map.

I think you could use a map whose keys are calculated with the values you use as parameters of your find method (taking into account that the combination of them gives a unique identifier of a 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));
    }
}

Hope it helps.

like image 50
acontell Avatar answered Nov 15 '22 05:11

acontell