I have a List of object and the list is very big. The object is
class Sample {
String value1;
String value2;
String value3;
String value4;
As your list is an ArrayList
, it can be assumed that it is unsorted. Therefore, there is no way to search for your element that is faster than O(n).
If you can, you should think about changing your list into a Set
(with HashSet
as implementation) with a specific Comparator
for your sample class.
Another possibility would be to use a HashMap
. You can add your data as Sample
(please start class names with an uppercase letter) and use the string you want to search for as key. Then you could simply use
Sample samp = myMap.get(myKey);
If there can be multiple samples per key, use Map<String, List<Sample>>
, otherwise use Map<String, Sample>
. If you use multiple keys, you will have to create multiple maps that hold the same dataset. As they all point to the same objects, space shouldn't be that much of a problem.
With Java 8 you can simply convert your list to a stream allowing you to write:
import java.util.List;
import java.util.stream.Collectors;
List<Sample> list = new ArrayList<Sample>();
List<Sample> result = list.stream()
.filter(a -> Objects.equals(a.value3, "three"))
.collect(Collectors.toList());
Note that
a -> Objects.equals(a.value3, "three")
is a lambda expressionresult
is a List
with a Sample
typelist.parallelStream()
instead of list.stream()
(read this)If you can't use Java 8, you can use Apache Commons library and write:
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
Collection result = CollectionUtils.select(list, new Predicate() {
public boolean evaluate(Object a) {
return Objects.equals(((Sample) a).value3, "three");
}
});
// If you need the results as a typed array:
Sample[] resultTyped = (Sample[]) result.toArray(new Sample[result.size()]);
Note that:
Object
to Sample
at each iterationSample[]
, you need extra code (as shown in my sample)Bonus: A nice blog article talking about how to find element in list.
I modifie this list and add a List to the samples try this
Pseudocode
Sample {
List<String> values;
List<String> getList() {
return values}
}
for(Sample s : list) {
if(s.getString.getList.contains("three") {
return s;
}
}
You can give a try to Apache Commons Collections.
There is a class CollectionUtils that allows you to select or filter items by custom Predicate.
Your code would be like this:
Predicate condition = new Predicate() {
boolean evaluate(Object sample) {
return ((Sample)sample).value3.equals("three");
}
};
List result = CollectionUtils.select( list, condition );
Update:
In java8, using Lambdas and StreamAPI this should be:
List<Sample> result = list.stream()
.filter(item -> item.value3.equals("three"))
.collect(Collectors.toList());
much nicer!
If you always search based on value3
, you could store the objects in a Map:
Map<String, List<Sample>> map = new HashMap <>();
You can then populate the map with key = value3
and value = list of Sample objects with that same value3
property.
You can then query the map:
List<Sample> allSamplesWhereValue3IsDog = map.get("Dog");
Note: if no 2 Sample
instances can have the same value3
, you can simply use a Map<String, Sample>
.