Is there a method in JDK or apache commons to "pop" a list of elements from a java.util.List? I mean, remove the list of elements and return it, like this method:
public Collection pop(Collection elementsToPop, Collection elements) {
Collection popped = new ArrayList();
for (Object object : elementsToPop) {
if (elements.contains(object)) {
elements.remove(object);
popped.add(object);
}
}
return popped;
}
If you're looking for a stack-like structure I suggest accepting a Deque (LinkedList is the most common implementation) instead of a Collection.
If you don't actually need to treat it as a stack, just get an iterator from the Collection and use the remove() method:
for (Iterator<SomeType> it = elements.iterator(); it.hasNext(); ) {
SomeType e = it.next();
it.remove();
popped.add(e);
}
Do note that remove is an optional operation, and some implementations may throw an UnsupportedOperationException (for example, the iterator returned by a Collection from Collections.unmodifiable...() will).
Edit: After looking more closely at your question, I think you just need this:
elements.removeAll(elementsToRemove);
If your main point is you need to know exactly which elements were actually popped, I think you're stuck with your original code.
There is no such method in the standard JDK-provided methods. Apache Commons provides the ListUtils.subtract() method.
Edit: As other answerers have noted, your use of the term pop is nonstandard. Usually,
The pop operation removes an item from the top of [a stack]
Wikipedia has a nice description of stacks.
I guess no, because you definition of 'pop' operation is highly non-standard. Usually it takes no arguments (except collection itself) and returns and removes the top-most one.
But once you noted apache commons, this would achieve the same effect as your code.
Collection result = CollectionUtils.intersection(a, b);
a.removeAll(b);
edit
http://commons.apache.org/collections/api-release/index.html
Linked List provides the functionality as you require, provides a push and pop method.
Refer to the documentation as provided:
There isn't a method exactly like what you are asking for, but it looks like you are already pretty close with your code.
Some suggestions:
Consider using removeAll(object) instead of remove(object) if elements is an arbitrary collection since you may need to remove duplicates e.g. if elements is a list.
contains() is slow for some collection types (e.g. lists) since it needs to traverse the entire data structure. Given that this is in your inner loop you are at risk of O(n^2) performance issues. If you can make the algorithm work with a HashSet or HashMap then contains() will by O(1) and your algorithm will be much more efficient.
Related
Even if it's easy to make an handle make, but I wonder if there is any famous helper help to get the size of a list or to get the last object of a list. I think it is really a popular requirements, but I couldn't found one.
size = list==null? 0: list.size();
lastObject = isEmpty(list)? null:list.get(list.size() - 1).
Thanks,
Those don't seem all that helpful to me. I try to initialize my lists so they're not null, so the first one is not useful at all. As for the second, it's no more useful to get back a possibly-null object (which then has to be tested to see if it's null) than it is to check the size of the list first.
There isn't a helper method for this AFAIK. One thing you should make sure is that when writing your own helper utility, pay special attention to your target collection. If it is a List, avoid using get(index) since it is not very efficient for a linked list implementation. If it is an ArrayList or in general any collection which implements RandomAccess, get is very efficient. The most generic way would be to obtain an iterator for the last element and invoke next() on it if it exists.
public static <T> T getLast(final List<T> list) {
final ListIterator<T> listIterator = list.listIterator(list.size());
return listIterator.hasPrevious() ? listIterator.previous() : null;
}
Google Guava has a getLast method. However, I couldn't find a size method that handles null Collections.
I have a list of Strings and I want to perform the same operation on all of the Strings in the list.
Is it possible without performing a loop?
Well something's got to loop, somewhere - if you want to abstract that into your own method, you could do so, but I don't believe there's anything built into the framework.
Guava has various methods in Iterables to perform projections etc, but if you want to modify the list on each step, I'm not sure there's any support for that. Again, you could write your own method (extremely simply) should you wish to.
When Java eventually gets closures, this sort of thing will become a lot more reasonable - at the moment, specifying the "something" operation is often more effort than it's worth compared with hard-coding the loop, unfortunately.
You could do it recursively, but I don't see why you'd want to. You may be able to find something similar to Python's map function (which, behind the scenes, would either be a loop or a recursive method)
Also note that strings are immutable - so you'll have to create 'copies' anyway.
No. You must loop through the list.
for(String s:yourlist){
dooperation(s);
}
Why do you not want to perform a loop?
If it's computational complexity, then no, it's unavoidable. All methods will essentially boil down to iterating over every item in the list.
If it's because you want something cleaner, then the answer depends on what you think is cleaner. There are various libraries that add some form of functional map, which would end up with something like:
map(list, new Mapper<String, String>() {
public String map(String input) {
return doSomethingToString(input);
}
);
This is obviously more long winded and complex than a simple loop
for (int i = 0; i < list.size(); i += 1) {
list[i] = doSomethingToString(list[i]);
}
But it does offer reusability.
map(list, new DoSomethingToStringMapper());
map(otherlist, new DoSomethingToStringMapper());
But probably you don't need this. A simple loop would be the way to go.
You could use apache commons util.
sorry, you have to iterate through the list somehow, and the best way is in a loop.
Depending on what you mean by no loop, this may interest you:
a map function for java.
http://www.gubatron.com/blog/2010/08/31/map-function-in-java/
...there's still a loop down inside of it.
In Java you'll need to iterate over the elements in the Collection and apply the method. I know Groovy offers the * syntax to do this. You could create an interface for your functions e.g. with an apply method and write a method which takes your Collection and the interface containing the function to apply if you want to add some general API for doing this. But you'll need the iteration somewhere!
Use divide and conquer with multithreaded traversal. Make sure you return new/immutable transformed collection objects (if you want to avoid concurrency issues), and then you can finally merge (may be using another thread which will wake up after all the worker threads finished transformer tasks on the divided lists?).
If lack of memory in creating these intermediate collections, then synchronize on your source collection. Thats the best you can do.
No you have to use a loop for that.
You have to perform the operation on each reference variable to the Strings in the List, so a loop is required.
If its at the List level, obviously there are some operations (removeAll, etc.).
The java API provides special class to store and manipulate group of objects. One Such Class is Arraylist
Note that Arraylist class is in java.util.ArrayList
Create an ArrayList as you would any objects.
import java.util.ArrayList;
//..
ArrayList ajay = new ArrayList();
Here
ArrayList -> Class
ajay -> object
You can optionally specify a capacity and type of objects the Arraylist will hold:
ArrayList ajay<String> = new ArrayList<String>(10);
The Arraylist class provides a number of useful methods for manipulating objects..
The add() method adds new objects to the ArrayList.And remove() method remove objects from the List..
Sample code:
import java.util.ArrayList;
public class MyClass {
public static void main(String[ ] args) {
ArrayList<String> ajay = new ArrayList<String>();
ajay.add("Red");
ajay.add("Blue");
ajay.add("Green");
ajay.add("Orange");
ajay.remove("Green");
System.out.println(colors);
}
}
Output for this Code:
[Red,Blue,Orange]
Accepted answer link is broken and solution offered is deprecated:
CollectionUtils::forAllDo
#Deprecated
public static <T,C extends Closure<? super T>> C forAllDo(Iterable<T> collection, C closure)
Deprecated. since 4.1, use IterableUtils.forEach(Iterable, Closure) instead
Executes the given closure on each element in the collection.
If the input collection or closure is null, there is no change made.
You can use IterableUtils::forEach(Closure c)
Applies the closure to each element of the provided iterable.
I have 100,000 objects in the list .I want to remove few elements from the list based on condition.Can anyone tell me what is the best approach to achieve interms of memory and performance.
Same question for adding objects also based on condition.
Thanks in Advance
Raju
Your container is not just a List. List is an interface that can be implemented by, for example ArrayList and LinkedList. The performance will depend on which of these underlying classes is actually instantiated for the object you are polymorphically referring to as List.
ArrayList can access elements in the middle of the list quickly, but if you delete one of them you need to shift a whole bunch of elements. LinkedList is the opposite i nthis respect., requiring iteration for the access but deletion is just a matter of reassigning pointers.
Your performance depends on the implementation of List, and the best choice of implementation depends on how you will be using the List and which operations are most frequent.
If you're going to be iterating a list and applying tests to each element, then a LinkedList will be most efficient in terms of CPU time, because you don't have to shift any elements in the list. It will, however consume more memory than an ArrayList, because each list element is actually held in an entry.
However, it might not matter. 100,000 is a small number, and if you aren't removing a lot of elements the cost to shift an ArrayList will be low. And if you are removing a lot of elements, it's probably better to restructure as a copy-with filter.
However, the only real way to know is to write the code and benchmark it.
Collections2.filter (from Guava) produces a filtered collection based on a predicate.
List<Number> myNumbers = Arrays.asList(Integer.valueOf(1), Double.valueOf(1e6));
Collection<Number> bigNumbers = Collections2.filter(
myNumbers,
new Predicate<Number>() {
public boolean apply(Number n) {
return n.doubleValue() >= 100d;
}
});
Note, that some operations like size() are not efficient with this scheme. If you tend to follow Josh Bloch's advice and prefer isEmpty() and iterators to unnecessary size() checks, then this shouldn't bite you in practice.
LinkedList could be a good choice.
LinkedList does "remove and add elements" more effective than ArrayList. and no need to call such method as ArrayList.trimToSize() to remove useless memory. But LinkedList is a dual-linked list, each element is wrapped as an Entry which needs extra memory.
I'm using LinkedHashSet. I want to insert items at the 0th position, like:
Set<String> set = new LinkedHashSet<String>();
for (int i = 0; i < n; i++) {
set.add(0, "blah" + i);
}
I'm not sure how linked hash set is implemented, is inserting going to physically move all addresses of current items, or is it the same cost as inserting as in a linked-list implementation?
Thank you
------ Edit ---------------
Complete mess up by me, was referencing ArrayList docs. The Set interface has no add(index, object) method. Is there a way to iterate over the set backwards then? Right now to iterate I'm doing:
for (String it : set) {
}
can we do that in reverse?
Thanks
Sets are, by definition, independent of order. Thus, Set doesn't have add(int , Object) method available.
This is also true of LinkedHashSet http://download.oracle.com/javase/6/docs/api/java/util/LinkedHashSet.html
LinkedHashSet maintains insertion order and thus all elements are added at the end of the linked list. This is achieved using the LinkedHashMap. You can have a look at the method linkEntry in LinkedHashMap http://www.docjar.com/html/api/java/util/LinkedHashMap.java.html
Edit: in response to edited question
There is no API method available to do this. But you can do the following
Add Set to a List using new ArrayList(Set)
Use Collections.reverse(List)
Iterate this list
Judging by the source code of LinkedHashMap (which backs LinkedHashSet -- see http://www.docjar.com/html/api/java/util/LinkedHashMap.java.html ), inserts are cheap, like in a linked list.
To answer your latest question, there is no reverse iterator feature available from LinkedHashSet, even though internally the implementation uses a doubly linked list.
There is an open Request For Enhancement about this:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4848853
Mark Peters links to functionality available in guava, though their reverse list actually generates a reverse list.
As already mentioned, LinkedHashSet is build on LinkedHashMap, which is built on HashMap :) Javadocs says that it takes constant time to add an element into HashMap, assuming that your hash function is implemented properly. If your hash function is not implemented well, it may take up to O(n).
Iteration backwards in not supported at this moment.
You can't add elements to the front of a LinkedHashSet... it has no method such as add(int, Object) nor any other methods that make use of the concept of an "index" in the set (that's a List concept). It only provides consistent iteration order, based on the order in which elements were inserted. The most recently inserted element that was not already in the set will be the last element when you iterate over it.
And the Javadoc for LinkedHashSet explicitly states:
Like HashSet, it provides constant-time performance for the basic operations (add, contains and remove), assuming the hash function disperses elements properly among the buckets.
Edit: There is not any way to iterate over a LinkedHashSet in reverse short of something like copying it to a List and iterating over that in reverse. Using Guava you could do that like:
for (String s : Lists.reverse(ImmutableList.copyOf(set))) { ... }
Note that while creating the ImmutableList does require iterating over each element of the original set, the reverse method simply provides a reverse view and doesn't iterate at all itself.
I very much like the for-each-loop construction (for(T e : iterable)) in Java which works on any Iterable<T> because it makes in many cases very easy to read and to write code.
I wonder though if there is any way that I can access the underlying iterator from such a loop. This can be mandatory if I want to use the remove() from the iterator.
No, the whole point of the for-each-loop is to abstract away the underlying iterator.
If you need it, you must declare it.
No, you cannot remove objects in a for each loop.
Use this instead:
Iterator<Type> it = collection.iterator();
while (it.hasNext()) {
if (it.next().shouldBeRemoved()) {
it.remove();
}
}
Use a for loop instead.
If the collection is reasonably small, you can alternatively use a copy of the collection to iterate if you want to be able to remove elements so you won't have to act as if you have two collections.
for(T e : collection.clone())
if(e.shouldBeRemoved())
collection.remove();
Even better, Apache CollectionUtils (and there is probably a Google alternative and a generics alternative) provides filter(java.util.Collection collection, Predicate predicate). This example returns the whole list. You can store a predicate for reuse.
CollectionUtils.filter(collection, new Predicate(){
boolean evaluate(Object object){return true;}
});
You are correct, using an Iterator supports the ability to remove an object from a source collection safely, by calling remove() on the Iterator itself. The point here is to avoid a ConcurrentModifiedException which implies that a collection was modified while an Iterator was open against it. Some collections will let you get away with removing or adding elements to a Collection while iterating across it, but calling remove() on the Iterator is a safer practice.
But Iterator supports a derived and more powerful cousin ListIterator, only available from Lists, supports both adding and removing from a List during iteration, as well as bidirectional scrolling through Lists.
modifying data has a wrong feel to it, Just create a new Iterable(or collection) and add the items you want to keep to it, the other times are lost in the for loop ((kinda**