Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

What is the fastest way to get the selected objects from an array?

MyObject[] objects = new MyObject[]{new MyObject(true), new MyObject(false)};
MyObject[] selectedObjects = ???

Is there a faster way than:

ArrayList<MyObject> selObjectsList = new ArrayList<MyObject>();
for(MyObject obj : objects){
   if(obj.isSelected()){
       selObjectsList.add(obj);
   }
}
selectedObjects = selObjectsList.toArray(new MyObject[0]);

This are many lines for a simple operation, is there a shorter operation to do the same?

share|improve this question
This could help stackoverflow.com/questions/2082449/… – Jai Apr 15 at 11:36
You can make the code neater by reducing the number of lines required, but your not going to find anything faster than a O(n) iteration. – Perception Apr 15 at 11:39

4 Answers

up vote 3 down vote accepted

With the standard libraries, there is no (fundamentaly) neater way to do it. But there are numerous third-party libraries that have filter or predicate support. Google Collections comes to mind. And I have also heard good things about LambdaJ. Hopefully, things will improve with Java 8!

With LambdaJ it could look something like this:

select(myList, having(on(MyObject.class).isSelected()));

Edit I interpreted "fastest" as shortest number of lines. If it was performance you was thinking of, this answer might not be appropriate.

share|improve this answer
+1 on explaining interpretation and the caveat. – Dr H Apr 15 at 11:52
1  
Im using this a multiple times in my code, but it is always executed only once, so the big O doesn't matter. The code becomes much more readable now ;) – Jetse Apr 15 at 12:00

Unfortunately, no. If you are using an ArrayList, which is a linear list, then your are effectively forcing a linear search.

If you want to improve lookup, then you can use something like a Map that will allow quicker lookups, but you will have to use an intelligent method for setting the keys. For instance, if you were lookup up orders, you might use the order number as the key.

share|improve this answer

Use a Map.

  Map<Boolean, List<MyObject>> someMap;

Then you can do the following to retrieve the List of 'MyObjects' that are selected.

  someMap.get(true); 

And to populate...

  someMap.put(myObjectInstance.isSelected(), myObjectInstance);
share|improve this answer

You can combine apache commons-beanutils and commons-collections.

The short answer

 Predicate selectPredicate = new BeanPropertyValueEqualsPredicate(
        "selected", Boolean.TRUE);
 Collection selectedObjects = CollectionUtils.select(
        Arrays.asList(objects), selectPredicate);   

A Unit-Test example

import java.util.Arrays;
import java.util.Collection;

import org.apache.commons.beanutils.BeanPropertyValueEqualsPredicate;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.junit.Assert;
import org.junit.Test;

public class ObjectSelectionTest {

    @Test
    public void objectSelection() {
        MyObject obj1 = new MyObject();

        MyObject obj2 = new MyObject();
        obj2.setSelected(true);

        MyObject obj3 = new MyObject();
        MyObject[] objects = new MyObject[] { obj1, obj2, obj3 };

        Predicate selectPredicate = new BeanPropertyValueEqualsPredicate(
                "selected", Boolean.TRUE);
        Collection selectedObjects = CollectionUtils.select(
                Arrays.asList(objects), selectPredicate);

        Assert.assertEquals(1, selectedObjects.size());

        Object selected = selectedObjects.iterator().next();
        Assert.assertSame(obj2, selected);
    }

    public static class MyObject {
        private boolean selected;

        public boolean isSelected() {
            return selected;
        }

        public void setSelected(boolean selected) {
            this.selected = selected;
        }
    }
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.