Getting subset of elements from array having same value - java

Is there any collection API method that extracts the same elements from array or collection?
for example SomeClass.getElements("Test") should return subset of an array that holds elements with value "Test".
Reason for asking this question is because I want to avoid my own traverse and condition checks.
Regards,
Sudhakar

As mentioned in the comments, there are (presently) no easy ways to do this. The best you could do is something akin to http://docs.oracle.com/javase/6/docs/api/java/io/FilenameFilter.html , where you make an interface that accepts elements while iterating over it.
Alternatively, you can do something like: What is the best way to filter a Java Collection? , which drags you into the land of functional programming.

If you use the Apache collections api you can do:
Predicate predicate = PredicateUtils.equalPredicate("Test");
Collection result = CollectionUtils.find(someCollection, predicate);

Related

Selecting specific object(s) from list with Java

Probably some basic stuff I am missing here, but what is the best way to select objects matching some criteria from list?
Say we have:
class MyObject {
int id;
String type;
// getters..setters
}
I use it:
List<MyObject> myObjects = new ArrayList<MyObject>();
myObjects = getListOfObjects();
Now lets say that in the myObjects there are 10 items and 3 of them have type=="bla". At the moment I am just looping thru all the objects and within the loop decide if I want it or not, but is there a better way?
I remember that in C# I used to have something like
myObjects.Where(x => x.type.equals("bla"));
PS, I am targeting Java 7 so no lambda for me yet.
I don't think you can do this without creating an index of some kind. So e.g. having Map<String, Map<String, Set<MyObject>>> you could then call index.get("type").get("bla"). But you would have to first construct this structure. This would be useful if a) there are no changes to the properties AND b) you have a LOT of objects. For 10 objects the performance is of no concern here and I would simply just do what you're doing right now and hide it inside some nice handy method.
You could use the LambdaJ library and its Lambda.exists method with some custom Hamcrest matcher. Then you could make your main code look like this:
if (exists(myObjects, typeIs("bla"))) { /* ... */ }
...provided that you create that custom matcher method typeIs by yourself. But I wouldn't go down this way if I had just one place with just 10 items in a list.
It also depends on your data: if your list is sorted, you could do a binary search on it. That's more useful if you have thousands of items in the list, though.
Finally, you could just use Collection.contains: myObjects.contains(blaElement), but that requires that the blaElement has such an equals method that returns "true" when the type matches.

Filtering List without using iterator

I need to filter a List of size 1000 or more and get a sublist out of it.
I dont want to use an iterator.
1) At present I am iterating the List and comparing it using Java. This is time consuming task. I need to increase the performance of my code.
2) I also tried to use Google Collections(Guava), but I think it will also iterate in background.
Predicate<String> validList = new Predicate<String>(){
public boolean apply(String aid){
return aid.contains("1_15_12");
}
};
Collection<String> finalList =com.google.common.collect.Collections2.filter(Collection,validList);
Can anyone suggest me how can I get sublist faster without iterating or if iterator is used I will get result comparatively faster.
Consider what happens if you call size() on your sublist. That has to check every element, as every element may change the result.
If you have a very specialized way of using your list which means you don't touch every element in it, don't use random access, etc, perhaps you don't want the List interface at all. If you could tell us more about what you're doing, that would really help.
List is an ordered collection of objects. So You must to iterate it in order to filter.
I enrich my comment:
I think iterator is inevitable during filtering, as each element has to be checked.
Regarding to Collections2.filter, it's different from simple filter: the returned Collection is still "Predicated". That means IllegalArgumentException will be thrown if unsatisfied element is added to the Collection.
If the performance is really your concern, most probably the predicate is pretty slow. What you can do is to Lists.partition your list, filter in parallel (you have to write this) and then concatenate the results.
There might be better ways to solve your problem, but we would need more information about the predicate and the data in the List.

Stacking generics

Is this bad practice?
ArrayList<ArrayList<ArrayList<Double>>> list = new ArrayList<ArrayList<ArrayList<Double>>>();
It is a three-dimensional matrix based on ArrayList. Doesn't look nice, but that's how we have to write it.
An alternative could be:
List<List<List<Double>>> list = new ArrayList<List<List<Double>>>();
which is a bit shorter and usually OK as in most cases your just interested in the interface methods.
So if you need a resizable threedimensional matrix data structure, then this is a clean approach.
This is not necessarily bad practice. It's just "unreadable". Have a bit of patience, in the upcoming Java 7 you're allowed to omit the cruft in specific generic types when constructing the parameterized type:
List<List<List<Double>>> list = new ArrayList<>();
This is called type inference.
As of now, if you can live with compiler warnings, you can also just do so:
List<List<List<Double>>> list = new ArrayList();
It would probably be a good idea to create a new class to handle the behavior you are trying to accomplish. I would create a class that uses an private ArrayList<...> (favor delegation over inheritance) and create necessary methods. If anything it should make things easier to read and understand.
yes. most likely your code is better off with double[][][]
Well, do you need to have a List whose elements are Lists whose elements are Lists? We have no idea what it is you are trying to accomplish unless you tell us.
However, using ArrayList directly rather than List is indeed a bad practice.
Depends on how you intend to use this. Perhaps you could encapsulate the two dimensional list and end up with a List<TwoDimensionalList<Double>>. Presumably it would have operations such as TwoDimensionalList.get(int i, int j) to get an element in the jth position of the ith list.
edit: if it's not a list of two dimensional lists, but rather a three dimensional list, then of course you want a ThreeDimensionalList. (and if your list's dimensions are fixed, you could implement this internally with a single array(list) where element (i,j,k) is located at position i*dim1 + j*dim2 + k*dim3).
At the least, naming it more expressively, something like 3dList, would help.
Preferred, for me, is to write a custom encapsulation of 2D/3D list, as others have suggested above.

Is there a writable iterator in Java?

In C+ one can use iterators for writing to a sequence. Simplest example would be:
vector<int> v;
for (vector<int>::iterator it = v.begin(); it!=v.end(); ++it) {
*it = 42;
}
I need something more complicated - keep iterator as a class member for a later use.
But I don't know how to get this behavior from Java iterators.
Are there writable iterators in Java at all?
If not then what replaces them?
The ListIterator (which you can obtain by List#listIterator()) has add() and set() methods which allows you to respectively insert and replace the item at the currently iterated index. That's as far the only "writable iterator" as I can think of in Java.
Not sure though if that is the exact replacement of the given C++ code since I don't know C++.
As arrays can be accessed directly and quickly by their index, you don't really need an iterator object. Wouldn't it be enought to save the index of the array in that class member? This would permit to read and write the value of the array.
PS: You could use an ArrayList, which is an automatically growing set of arrays and use the ListIterator as Balus described in order to use the iterator-object-approach.
Looks more like you want a List (or maybe some other collection, like Set) or an array.
Also, you could just make your contents mutable. It looks silly for integers, but continuing your example
for (MutableInteger i : CollectionOfMInts) i.setTo(42);

Best way to remove repeats in a collection in Java?

This is a two-part question:
First, I am interested to know what the best way to remove repeating elements from a collection is. The way I have been doing it up until now is to simply convert the collection into a set. I know sets cannot have repeating elements so it just handles it for me.
Is this an efficient solution? Would it be better/more idiomatic/faster to loop and remove repeats? Does it matter?
My second (related) question is: What is the best way to convert an array to a Set? Assuming an array arr The way I have been doing it is the following:
Set x = new HashSet(Arrays.asList(arr));
This converts the array into a list, and then into a set. Seems to be kinda roundabout. Is there a better/more idiomatic/more efficient way to do this than the double conversion way?
Thanks!
Do you have any information about the collection, like say it is already sorted, or it contains mostly duplicates or mostly unique items? With just an arbitrary collection I think converting it to a Set is fine.
Arrays.asList() doesn't create a brand new list. It actually just returns a List which uses the array as its backing store, so it's a cheap operation. So your way of making a Set from an array is how I'd do it, too.
Use HashSet's standard Collection conversion constructor. According to The Java Tutorials:
Here's a simple but useful Set idiom.
Suppose you have a Collection, c, and
you want to create another Collection
containing the same elements but with
all duplicates eliminated. The
following one-liner does the trick.
Collection<Type> noDups = new HashSet<Type>(c);
It works by creating a Set (which, by
definition, cannot contain a
duplicate), initially containing all
the elements in c. It uses the
standard conversion constructor
described in the The Collection
Interface section.
Here is a minor variant of this idiom
that preserves the order of the
original collection while removing
duplicate element.
Collection<Type> noDups = new LinkedHashSet<Type>(c);
The following is a generic method that
encapsulates the preceding idiom,
returning a Set of the same generic
type as the one passed.
public static <E> Set<E> removeDups(Collection<E> c) {
return new LinkedHashSet<E>(c);
}
Assuming you really want set semantics, creating a new Set from the duplicate-containing collection is a great approach. It's very clear what the intent is, it's more compact than doing the loop yourself, and it leaves the source collection intact.
For creating a Set from an array, creating an intermediate List is a common approach. The wrapper returned by Arrays.asList() is lightweight and efficient. There's not a more direct API in core Java to do this, unfortunately.
I think your approach of putting items into a set to produce the collection of unique items is the best one. It's clear, efficient, and correct.
If you're uncomfortable using Arrays.asList() on the way into the set, you could simply run a foreach loop over the array to add items to the set, but I don't see any harm (for non-primitive arrays) in your approach. Arrays.asList() returns a list that is "backed by" the source array, so it doesn't have significant cost in time or space.
1.
Duplicates
Concurring other answers: Using Set should be the most efficient way to remove duplicates. HashSet should run in O(n) time on average. Looping and removing repeats would run in the order of O(n^2). So using Set is recommended in most cases. There are some cases (e.g. limited memory) where iterating might make sense.
2.
Arrays.asList() is a cheap operation that doesn't copy the array, with minimal memory overhead. You can manually add elements by iterating through the array.
public static Set arrayToSet(T[] array) {
Set set = new HashSet(array.length / 2);
for (T item : array)
set.add(item);
return set;
}
Barring any specific performance bottlenecks that you know of (say a collection of tens of thousands of items) converting to a set is a perfectly reasonable solution and should be (IMO) the first way you solve this problem, and only look for something fancier if there is a specific problem to solve.

Categories

Resources