7

Say I have

    List<SomeObject> objList = new ArrayList<SomeObject>();

If SomeObject contains a field named id. Can we find it through some query like

objList.filter('id=2');

without looping through the list? If not, then why? This can be such a useful method and can be used as an alternative to write a tedious for loop.

SternK
  • 11,649
  • 22
  • 32
  • 46
TCM
  • 16,780
  • 43
  • 156
  • 254
  • See http://stackoverflow.com/questions/122105/java-what-is-the-best-way-to-filter-a-collection – YuppieNetworking May 17 '10 at 11:18
  • Thanks Yuppie. Yours is the most relevant answer. – TCM May 17 '10 at 11:33
  • 1
    You can do objList.select(idEqualTo(2)) when using this library https://github.com/nicholas22/jpropel-light. You have to define the function idEqualTo() but it's a one-liner. – NT_ Oct 08 '11 at 10:35
  • Similar question http://stackoverflow.com/questions/2846771/how-to-selectively-filter-items-in-a-collection – Sujee May 17 '10 at 11:19

6 Answers6

8

Libraries with functional, well, functionality such as functionaljava provide such methods.

You'd need to use its own List implementation which is incompatible to native Javas (Array)List or convert between the two.

An Example:

import fj.data.Java
import fj.data.List
import fj.F

// Converting an ArrayList
fj.data.List<SomeObject> objList2 = Java.ArrayList_List().f(objList);

fj.data.List<SomeObject> filteredObjList = objList2.filter(new F<SomeObject, Boolean>() {
  Boolean f(SomeObject c) { return c.id == 2; } 
});

// Converting back to ArrayList
java.util.List<SomeObject> objList2 = Java.List_ArrayList().f(filteredObjList );

By using functionaljava's List through out of your project you would avoid the converting.

RoToRa
  • 37,635
  • 12
  • 69
  • 105
2

Probably this will help someone,

http://code.google.com/p/joquery/

this library supports following code structure,

Filter<Dto> query = CQ.<Dto>filter(testList)
    .where()
    .property("id").eq().value(1);
Collection<Dto> filtered = query.list();
Low Flying Pelican
  • 5,974
  • 1
  • 32
  • 43
2

Even if this was a supported feature of the language, then it would be Java that would need to do the iterating, so you're back at square one (in terms on time complexity).

What you're looking for is associative mapping. This can be achieved with HashMap. If you want to associate by more than one type of property for example id AND name, then you could make two HashMaps, one whose key is id and one whose key is name.

This of course doesn't scale very well if you want to query for many properties, so the next step would be using an Object oriented database such as Hibernate which will allow you to query the database for objects exactly as in your example.

Martin Konecny
  • 57,827
  • 19
  • 139
  • 159
  • 1
    Well, i am not worried about running time. I am more worried about my coding time (my productivity). Just one extra method call is not going to miserably slow down my application. And i don't want to use Hashtable kind of data structure. Actually i want something similar to what Linq offers in .Net where you can directly query a collection – TCM May 17 '10 at 11:25
  • @Nitesh, Sorry not familiar with .NET. But you cannot query a collection in Java as in your example (there may be some 3rd party frameworks or libraries that do this). – Martin Konecny May 17 '10 at 11:34
2

short: no, you can't

long: you can write own data structure and hash/index fields of object for some more efficient search. but this is not a list, more HashMap or so.

p4553d
  • 818
  • 1
  • 7
  • 17
1

If you want something like linq for java, check out quaere


Edit: At this point, quaere looks like it is unmaintained. With Java 7 being EOL, you should be on Java 8 whose Stream API should get you most of the way there when compared to Linq's dot syntax. See this page for some examples.

whaley
  • 16,075
  • 10
  • 57
  • 68
0

Here How do you query object collections in Java (Criteria/SQL-like)? you can see some nice option/ I've sopped on this one actually.

Community
  • 1
  • 1
Der Zinger
  • 506
  • 7
  • 13