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?
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.
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.
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);
Related
List<VO> list = new ArrayList<VO>();
I have another list of type object[] which contains nearly 100 items.Then i need to
iterate and put those values into vo.So i write the following code.
for(Object[] obj:list1){
VO vo = new VO();
vo.setName(obj[0].toString);
.....
}
Here i am creating 100 objects.But i heard creating too much objects will decrease the
performance.Is there any way to reduce no of objects here.Thanks in advance...
If your list has to have 100 references to different VO objects in the end, then there's no way you can avoid creating them, pretty much by definition.
While creating too many objects can indeed create performance problems, you probably shouldn't worry about that at the moment. Creating 100 objects it incredibly cheap in general. You should focus on writing clear code, and then measuring performance - only start trying to think of complex ways of improving performance after you've got something which works, but not fast enough.
No, based off the given information, there is no way to do that without creating one V0 object for each Object in list1.
However, Java shouldn't slow down doing this. 100 objects is really a rather inexpensive operation.
As an aside: I suggest using better names for your variables. Yours are confusing and needlessly short.
What is the real type of the formal type Object? Certainly, the real type is not object, then toString would print out just the ObjectID. I cannot believe that this is what you want.
So, what is the real type? Wouldn't be a type cast to the VO object enough?
List list = (new ArrayList()).addAll(list1);
Assuming that list1 contains only VO objects.
You can keep a reference to the original object in list1 wnd keep list1 available, something like this:
for(Object[] obj:list1){
list.add((VO)obj);
}
Or:
List<VO> list = new ArrayList<VO>(list1);
Is there a way to compact a HashMap in the sense that you can with an ArrayList through its trimToSize() method?
One way I can think of is to iterate through all of the entries in the present map and populate a new one, then replace the original with the new one.
Is there a better way to accomplish this?
Well you don't need to go through iterating manually - you can just use:
map = new HashMap<String, String>(map); // Adjust type arguments as necessary
I believe that will do all the iteration for you. It's possible that clone() will do the same thing, but I don't know for sure.
Either way, I don't believe you're missing anything - I don't think there's any way of performing a "trim" operation in the current API. Unlike ArrayList, such an operation would be reasonably complex anyway (as expansion is) - it's not just a case of creating a new array and performing a single array copy. The entries need to be redistributed. The benefit of getting HashMap to do this itself internally would probably just be that the hash codes wouldn't need recomputing.
If you use the trove library instead this has support for hash map and hash set trimming (see THashMap object, compact method) and best of all, automatically trims on removal of objects when the map becomes too sparse. This should be quicker than building a new map using the standard java HashMap implementation as (presumably) it doesn't have to reorder the objects according to their hashcode, but can just use the order it already knows.
given the following code?
final Map<String, List<E>> map = new HashMap<String, List<E>>();
List<E> list = map.get(mapKey);
if (list == null) {
list = new ArrayList<E>();
map.put(mapKey, list);
}
list.add(value);
If there any way I can avoid the null check? But let the Map automatically create the List for me for my first time insertion?
I remember I once saw a specialized Map which is able to do this. However, I forget where I saw already :(
You are looking for Guava's* MultiMap. You may have previously heard about it when it was called "Google Collections".
This blog post talks a little about the MultiMap.
You could use Multimap from Guava... that's what I'd do :) (And in particular, an ArrayListMultimap.)
If you could, it might save a nanosecond and is probably not worth spending a lot of time figuring out. If however you are trying to optimize for performance and you have so many or such big maps that this is causing performance issues, you might consider Javolution. They have a fast map and fast list that perform much better than Java's default map and list.
There is a MultiValueMap in apache's commons-collections
If you have a small number of items an array might actually be faster. The overhead of more complex data types is not needed when you have a few items and a linear search helps the JVM load the items faster.
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.
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.
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.
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.
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();
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.
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.
Often, I have a list of objects. Each object has properties. I want to extract a subset of the list where a specific property has a predefined value.
Example:
I have a list of User objects. A User has a homeTown. I want to extract all users from my list with "Springfield" as their homeTown.
I normally see this accomplished as follows:
List users = getTheUsers();
List returnList = new ArrayList();
for (User user: users) {
if ("springfield".equalsIgnoreCase(user.getHomeTown())
returnList.add(user);
}
I am not particularly satisfied with this solution. Yes, it works, but it seems so slow. There must be a non-linear solution.
Suggestions?
Well, this operation is linear in nature unless you do something extreme like index the collection based on properties you expect to examine in this way. Short of that, you're just going to have to look at each object in the collection.
But there may be some things you can do to improve readability. For example, Groovy provides an each() method for collections. It would allow you to do something like this...
def returnList = new ArrayList();
users.each() {
if ("springfield".equalsIgnoreCase(it.getHomeTown())
returnList.add(user);
};
You will need a custom solution for this. Create a custom collection such that it implements List interface and add all elements from original list into this list.
Internally in this custom List class you need to maintain some collections of Map of all attributes which can help you lookup values as you need. To populate this Map you will have to use introspection to find list of all fields and their values.
This custom object will have to implement some methods as List findAllBy(String propertyName, String propertyValue); that will use above hash map to look up those values.
This is not an easy straightforward solution. Further more you will need to consider nested attributes like "user.address.city". Making this custom List immutable will help a lot.
However even if you are iterating list of 1000's of objects in List, still it will be faster so you are better off iterating List for what you need.
As I have found out, if you are using a list, you have to iterate. Whether its a for-each, lambda, or a FindAll - it is still being iterated. No matter how you dress up a duck, it's still a duck. As far as I know there are HashTables, Dictionaries, and DataTables that do not require iteration to find a value. I am not sure what the Java equivalent implementations are, but maybe this will give you some other ideas.
If you are really interested in performance here, I would also suggest a custom solution. My suggestion would be to create a Tree of Lists in which you can sort the elements.
If you are not interested about the ordering of the elements inside your list (and most people are usually not), you could also use a TreeMap (or HashMap) and use the homeTown as key and a List of all entries as value. If you add new elements, just look up the belonging list in the Map and append it (if it is the first element of course you need to create the list first). If you want to delete an element simply do the same.
In the case you want a list of all users with a given homeTown you just need to look up that list in the Map and return it (no copying of elements needed), I am not 100% sure about the Map implementations in Java, but the complete method should be in constant time (worst case logarithmic, depending on the Map implementation).
I ended up using Predicates. Its readability looks similar to Drew's suggestion.
As far as performance is concerned, I found negligible speed improvements for small (< 100 items) lists. For larger lists (5k-10k), I found 20-30% improvements. Medium lists had benefits but not quite as large as bigger lists. I did not test super large lists, but my testing made it seem the large the list the better the results in comparison to the foreach process.