Run a select query with a desired range in memory on POJO.


You have an object Game with 'country' and 'timestamp' fields and you are looking for all games played in Germany between 12.05.2012 and 20.05.2014.

And for some reason you would like to do so in memory without any DB.

Lets say that the list of countries isn't huge and the timestamp 2014.06.25 12:45:22 is saved in the following format, by removing spaces and dots : 20140625124522 .

public class Game implements Comparator<Game>{
    public enum Country{GERMANY, BRASIL} 

    private String country;
    private String metadata;
    private long dateLong;
    public Game(){}
    public Game(String country, String metadata, long dateLong) { = country;
        this.metadata = metadata;

    public int compare(Game o1, Game o2) { 
        return (int) (o1.getDateLong() - o2.getDateLong()); 


- Separate each country to its own list. (save map of all these lists)

- Sort each list by timestamp.

- Extract the timestamps from each list to an external list (save map of them).

- Run the select query on the list of timestamps and get the result sublist from the list of countries by using the found corresponding indexes.


The main point is to find the closest timestamp for the start/end dates. For example, you are looking for period of time between 12.05.2012 and 20.05.2014 but your data set starts from 1.01.2013 and you have some data for 19.05.2014 and 21.05.2014 but not for 20.05.2014 specifically.

In this case, the closest start date should be 1.01.2013 and the closest end date will be 19.05.2014. Now, we are able to find the right indexes of these dates. For example, we found the start index = 0 and the end index = 305 in the sorted list of timestamps, but these indexes are also correct in the list of its corresponding country, therefore you can use them in order to get the resulting sublist.


Lets see an example of one country:

private List<Game> gameList = new ArrayList<>();
private List<Game> germanyList = new ArrayList<>();
private List<Long> germanyDateList = new ArrayList<>();

    public void init(){
        // do: push the data to gameList
        for (Game game : gameList) { 
            String country = game.getCountry();
            if(country.compareTo(    {germanyList.add(game);}    

        Collections.sort(germanyList, new Game());

        for (Game game : germanyList) { 

public List<Game> findByCountryAndLongDate(String countryName, Long start,Long finish) {
        if(start == null && finish == null){
            return findByCountry(countryName);
            return findDataInTimeRange(germanyList, germanyDateList, start, finish);

        return Collections.emptyList(); 

private List<Game> findDataInTimeRange(List<Game> data, List<Long> dataIndex, Long start, Long finish) {
        start = start != null ? start :  dataIndex.get(0);
        finish = finish != null ? finish :  dataIndex.get(dataIndex.size()-1);
        int startIndex = getClosestIndex(dataIndex, start); 
        int endIndex = getClosestIndex(dataIndex, finish); 

        if(startIndex >=0 && endIndex >=0 ){
            return data.subList(startIndex, endIndex+1);
        return Collections.emptyList(); 

    private int getClosestIndex(List<Long> data, Long wanted) {
        int endIndex;
        endIndex = Collections.binarySearch(data, wanted);
        if (endIndex < 0) {
            long previousDate = data.get(Math.max(0, -endIndex - 2));
            long nextDate = data.get(Math.min(data.size() - 1, -endIndex - 1));
            endIndex = wanted - previousDate < nextDate - wanted ? (Math.max(0, -endIndex - 2)) : Math.min(data.size() - 1, -endIndex - 1);
        return endIndex;

For multiple countries you do the same but with maps:

Map<Game.Country, List<Game>> multiCountries = new HashMap<Game.Country, List<Game>>();
Map<Game.Country, List<Long>> multiDateList = new HashMap<Game.Country, List<Long>>();