views:

32

answers:

3

This task occurs from time to time in my projects. I need to handle a collection of some complex elements, having different attributes, such as login, password_hash, role, etc. And, I need to be able to query that collection, just like I query a table in the database, having only partial data. For example: get all users, with role "user". Or check, if there's a user with login "root" and role "superuser". Removing items, based on same data is also needed. The first attempt I've tried is to use Google collections, Apache collections, and lambdaj. All of them have very similar preicate mechanism, but with a great disadvantage: it is based on iteration, one by one, over the collection of items, which is not good, for often used collections, containing big amounts of data. Could you please suggest me some solution? Thanks.

UPDATE:

Currently I've solved this problem by implementing my custom collection, with multiple indexes , so that I can perform direct queries: http://code.google.com/p/tablej/

+1  A: 

You could embed a database into your app.
Here is a discussion on selecting the best embedded Java database.

The ones below are probably the top three (They are all free).

  • HSQLDB has a good reputation.
  • Java DB Java DB is included in the Java SE Development Kit, and is the developer database for the Sun GlassFish Enterprise Server. It also has a good reputation.
  • Berkeley DB Is a mature product, also high reputation.
Romain Hippeau
+1  A: 

Java can't do LINQ. It doesn't even come close, due to the lack of lambdas, yield, extension methods and expression trees. The quaere project offers a poor-man's substitute.

I don't think this will satisfy your algorithmic efficiency requirements, however. These can only be done in one of two ways, AFAIK:

  1. Hand-coded data structures, optimised for the questions you want to ask.
  2. In-memory HSQLDB.

The former is hard, but likely to yield the best performance. The latter won't be as fast, but it will be OK, especially if properly tuned with indexes, and much simpler to work with.

Marcelo Cantos
I don't think (2) is all that much easier to work with. If you don't want SQL strewn all over your code base you'd have to define some nice accessor objects (DAO's) anyway. Why not also put the data in there?
extraneon
+1  A: 

The database isn't automagically efficient either; you actually need to configure a database (by putting indices on relevant columns) for it to be able to do searches efficiently.

In a similar way you can optimize your code for speed. If you need to do a lot of lookups based on a few criteria you could make dedicated collections for that. Similar to an index on a database.

You'd do that by not only inserting your User into a Users list, but by putting that same user in for instance a Map keyed on Role:

public void addUser(User user) {
    users.add(user);
    // your index
    if (!usersByRole.containsKey(user.getRole()) {
       usersByRole.put(user.getRole(), new ArrayList<User>());
    }
    usersByRole.get(user.getRole()).add(user);
}

public List<User> findByRole(String role) {
    if (!usersByRole.containsKey(role)) {
        return Collectsions.emptyList();
    }
    return Collections.unmodifieableList(usersByRole.get(role));
}
extraneon