views:

152

answers:

4

I have a java list

List<myclass> myList = myClass.selectFromDB("where clause");

//myClass.selectFromDB returns a list of objects from DB

But I want a different list, specifically.

List<Integer> goodList = new ArrayList<Integer>();

for(int i = 0;i++; i<= myList.size()) {
    goodList[i] = myList[i].getGoodInteger();
}

Yes, I could do a different query from the DB in the initial myList creation, but assume for now I must use that as the starting point and no other DB queries. Can I replace the for loop with something much more efficient?

Thank you very much for any input, apologies for my ignorance.

+3  A: 

In order to extract a field from the "myclass", you're going to have to loop through the entire contents of the list. Whether you do that with a for loop, or use some sort of construct that hides the for loop from you, it's still going to take approximately the same time and use the same amount of resources.

Paul Tomblin
+3  A: 

An important question is: why do you want to do this? Are you trying to make your code cleaner? If so, you could write a method along these lines:

public static List<Integer> extractGoodInts (List<myClass> myList) {
    List<Integer> goodInts = new ArrayList<Integer>();

    for(int i = 0; i < myList.size(); i++){
        goodInts.add(myList.get(i).getGoodInteger());
    }

    return goodInts;
}

Then, in your code, you can just go:

List<myClass> myList = myClass.selectFromDB("where clause");
List<Integer> goodInts   = myClass.extractGoodInts(myList);

However, if you're trying to make your code more efficient and you're not allowed to change the query, you're out of luck; somehow or another, you're going to need to individually grab each int from the list, which means you're going to be running in O(n) time no matter what clever tricks you can come up with.

jboxer
You cannot create a List<int> in Java
Don
Also note that this method is static which points out a potential design flaw. It should actually be a member method of a class that wraps the List. Do that and you've got the start of an actual OO design here...
Bill K
Don: Good call on the int thing. It's been awhile since I've used Java.Bill K: Agreed, although wrapping the List might be somewhat overkill for something like this. I agree with you that the OO design could be cleaner, but I might argue that it's unnecessary complexity, and should only be refactored like that if we end up repeating this code for other types (Doubles, Strings, etc.) and other tables.
jboxer
A: 

There are really only two ways I can think of that you can make this more "efficient":

  1. Somehow split this up between multiple cores so you can do the work in parallel. Of course, this assumes that you've got other cores, they aren't doing anything useful already, and that there's enough processing going on that the overheard of doing this is even worth it. My guess is that (at least) the last point isn't true in your case given that you're just calling a getter. If you wanted to do this you'd try to have a number of threads (I'd probably actually use an Executor and Futures for this) equal to the number of cores, and then give roughly equal amounts of work to each of them (probably just by slicing your list into roughly equal sized pieces).

  2. If you believe that you'll only be accessing a small subset of the resulting List, but are unsure of exactly which elements, you could try doing things lazily. The easiest way to do that would be to use a pre-built lazy mapping List implementation. There's one in Google Collections Library. You use it by calling Lists.transform(). It'll immediately return a List, but it'll only perform your transformation on elements as they are requested. Again, this is only more efficient if it turns out that you only ever look at a small fraction of the output List. If you end up looking at the entire thing this will not be more efficient, and will probably work out to be less efficient.

Laurence Gonsalves
A: 

Not sure what you mean by efficient. As the others said, you have to call the getGoodInteger method on every element of that list one way or another. About the best you can do is avoid checking the size every time:

List<Integer> goodInts = new ArrayList<Integer>();
for (MyClass myObj : myList) {
   goodInts.add(myObj.getGoodInteger());
}

I also second jboxer's suggestion of making a function for this purpose.

Dan
You cannot create a List<int> in Java
Don
Good point. Fixed.
Dan