Trying to implement some reduceRight functionality.
For performance would be nice to iterate from right to left, without reversing everything first, and then going left to right. Normally we do:
Iteratable iterable ...;
Iterator iterator = iterable.iterator();
iterator.next();
but I am looking for something like:
Iteratable iterable ...;
Iterator iterator = iterable.reverseIterator();
iterator.next();
I see this solution: Iterating through a list in reverse order in java
The current accepted answer says that this works:
ArrayList<...> a = new ArrayList<...>();
// Add elements to list.
// Generate an iterator. Start just after the last element.
ListIterator li = a.listIterator(a.size());
// Iterate in reverse.
while(li.hasPrevious()) {
System.out.println(li.previous());
}
Anyone know how to implement reverse iteration given only an Iterable in hand? I don't have an ArrayList or List in hand, I have an Iterable in hand. I suppose I can convert the Iterable to an ArrayList, reverse the list, then get an iterator, but that would be no fun :)
Simple answer: not possible in a generic performant way.
The essence of iterator is to get you one direction, not both. And imagine a singlely linked list. That thing really has "only one direction"!
So the question how you can reverse an iterable thingy really requires you to look at the exact implementation.
Without that possibility, you have to use an intermediate data structure to fetch all entries before reversing.
You'll have to iterate over the original Iterator once in order to construct a reversed Iterator (assuming your original Iterator is finite).
For example:
static <T> Iterator<T> getReversedIterator(Iterable<T> iterable) {
Iterator<T> iter = iterable.iterator();
List<T> rev = new ArrayList<>();
while (iter.hasNext()) {
rev.add (0, iter.next());
}
return rev.iterator();
}
If you have an Iterable in hand, as you wrote in your question, then someone provided you with it. I would suggest asking the provider to supply an Iterable that supports reverse iteration.
Here is how I do it. If you are using a for loop, this will cause the original Iterator to be completely consumed and a new linked list to be created before the first iteration. This can obviously be an issue with large iterables, but it is predictable and easy to use. It has the advantage of working with anything that implements Iterable vs. some solutions that only work with specific types.
import java.util.Iterator;
public class Reversible<E> implements Iterable<E> {
private Iterable<E> source;
public Reversible(Iterable<E> source) {
this.source = source;
}
public Iterator<E> iterator() {
return new Reverserator<>(source.iterator());
}
public static class Reverserator<E> implements Iterator<E> {
private Entry<E> next = null;
private Reverserator(Iterator<E> source) {
while (source.hasNext()) {
next = new Entry<>(source.next(), next);
}
}
public boolean hasNext() {
return next != null;
}
public E next() {
Entry<E> curr = next;
next = curr.next;
return curr.obj;
}
private static class Entry<E> {
private E obj;
private Entry<E> next;
private Entry(E obj, Entry<E> next) {
this.obj = obj;
this.next = next;
}
}
}
}
It is quite simple to use:
List<String> names = new ArrayList<>();
names.add("George");
names.add("Fred");
names.add("Harry");
for (String name:new Reversible<>(names)) {
System.out.println(name);
}
Returns:
Harry
Fred
George
Related
I have an object list that retrieves multiple values from a database, like so:
List<Object> listRequest = daoManager.getLaptopsForRequest(BigInteger.valueOf(itemTransItem.getAssetType().getId()), BigInteger.valueOf(approverId));
The result of which looks like this (printed out on the console, via for each):
{asset_type_id=1, inventory_id=1, from_dt=2015-09-18 18:04:55.77, id=1, asset_id=1, status=1, thru_dt=null}
{asset_type_id=1, inventory_id=1, from_dt=2015-09-18 18:04:55.77, id=2, asset_id=2, status=1, thru_dt=null}
{asset_type_id=1, inventory_id=1, from_dt=2015-09-18 18:04:55.77, id=3, asset_id=3, status=1, thru_dt=null}
What's the quickest and/or most efficient way to get only the object where asset_id = 2, or an array of asset_id (1 and 2), and putting the results in another array?
I contemplated casting each object as a string, and then turning each string into an array (split by the comma), and then turning each item of the array into a further array (or a hashmap) by using the =, but that seems like a long, long, complex way of nested for loops that might fail (see comparing array of assets).
Perhaps there's another quicker / less complex way to do this that I'm missing? Any suggestions? Thanks.
EDIT: For reference, here's the getLaptopsForRequest function:
public List getLaptopsForRequest(BigInteger asset_type_id, BigInteger party_id){
SQLQuery query = sessionFactory.getCurrentSession().createSQLQuery(laptopsForRequestSql);
query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
List forRequest = query.setBigInteger(0, asset_type_id).setBigInteger(1, party_id).list();
return forRequest;
}
It returns a list of the results of the query. As this code has been in place, I'm not allowed to edit it.
A quick and dirty solution would be to match each item against regex ^.*asset_id=([0-9]+).*$.
If what you're getting from that method is indeed a list of Strings containing those JSONs, you could create a model class and use a JSON serializer like GSON or Jackson to read the strings into Java objects, and then you could work with them.
What you are trying to do basically is to filter a list of objects. You could implement the Filter Pattern writing your own Iterator for the list.
Just extends this class to implement your own filter.
public abstract class Filter<T> {
public abstract boolean passes(T object);
public Iterator<T> filter(Iterator<T> iterator) {
return new FilterIterator(iterator);
}
public Iterable<T> filter(Iterable<T> iterable) {
return new Iterable<T>() {
public Iterator<T> iterator() {
return filter(iterable.iterator());
}
};
}
private class FilterIterator implements Iterator<T> {
private Iterator<T> iterator;
private T next;
private FilterIterator(Iterator<T> iterator) {
this.iterator = iterator;
toNext();
}
public boolean hasNext() {
return next != null;
}
public T next() {
if (next == null)
throw new NoSuchElementException();
T returnValue = next;
toNext();
return returnValue;
}
public void remove() {
throw new UnsupportedOperationException();
}
private void toNext() {
next = null;
while (iterator.hasNext()) {
T item = iterator.next();
if (item != null && passes(item)) {
next = item;
break;
}
}
}
}
}
and then use it in this way:
List<MyObject> newList = new ArrayList<MyObject>();
for(MyObject obj : filter.filter(listObjs) ){
newList.add(obj);
}
Assuming your objects have getter et setter methods.
Only the object where asset_id = "2", asset_id here being a string
listRequest.stream().filter(e -> e.getAssetId() == "2" ).toArray();
I am looking for a way to find out in run-time, whether a collection is ordered or not. Any way to do this?
EDIT: I am sorry for wrongly asked question. I meant whether there is some general way to say HashMap does not store order of elements being inserted, where LinkedHashMap does.
For elements that implement the Comparable interface, you can check to see if they are in their "natural" order.
public static <T extends Comparable<? super T>> boolean isOrdered(Iterable<T> list) {
Iterator<T> i = list.iterator();
if (i.hasNext()) {
T previous = i.next();
while (i.hasNext()) {
T current = i.next();
if (previous.compareTo(current) > 0)
return false;
previous = current;
}
}
return true;
}
Otherwise, you'll have to define a Comparator that can compare your objects according to your definition of order, and pass that to the test.
public static <T> boolean isOrdered(Iterable<T> list, Comparator<? super T> c) {
Iterator<T> i = list.iterator();
if (i.hasNext()) {
T previous = i.next();
while (i.hasNext()) {
T current = i.next();
if (c.compare(previous, current) > 0)
return false;
previous = current;
}
}
return true;
}
Using the lovely and popular Guava libraries, it's a highly readable one-liner:
return Ordering.natural().isOrdered(collection);
If your elements are ordered according to some other comparator, and not their natural ordering:
return Ordering.from(comparator).isOrdered(collection);
Assuming it is a List, this should do it :-)
It compares every item (except the last - it will be checked by the second last item) and checks whether the next item is smaller. If that is the case then it isn't sorted.
for (int i = 0; i < collection.size() - 1; i++)
{
if (collection.get(i).compareTo(collection.get(i+1)) > 0)
{
// NOT SORTED
break;
}
}
Okay, so I'm supposed to implement a set that contains elements of type Object with no duplicates which means that I need to compare each new element with the previous elements in the set. The set has its own class and has a method for inserting a new element.
My question is: How do I use the iterator I wrote below to compare all the entries in the set with the proposed element to add?
class SetIterator implements MyIterator {
private ArraySet arr; //ArraySet is the name of the Set class
private int n;
SetIterator(ArraySet myArraySet)
{
arr = myArraySet;
n = 0;
}
#Override
public boolean hasNext()
{
return (n <= arr.size());
}
#Override
public Object next()
{
if (hasNext())
return arr[n++];
}
}
Thanks!
You'd need something like this in ArraySet.java.
public Iterator iterator()
{
return new SetIterator(this);
}
public boolean add(Object o)
{
for (Object item : this)
if (o.equals(next)) return false;
}
// add code to put o in the array
return true;
}
The for loop is translated by the compiler to something like this:
Iterator it = this.iterator();
while (it.hasNext())
{
Object item = it.next();
if (o.equals(next)) return false;
}
The implementation of Set should guarantee no-duplication rather than the Iterator.
That is, your Set.add() and its constructor with Collection as argument should guarantee no-duplication.
The Iterator just implements hasNext(), next(), and remove().
If Iterator takes care of duplication checking, your Set will violate java.util.Set contract. Moreover, the Iterator will take two responsibilities—checking duplication and traversing, that violates “Single Responsibily Principle”.
Yes, I just want an example on how to use that iterator instead of a for loop or a while loop.
You pretty much have to use some kind of loop to use a Iterator. Here is the basic pattern:
Iterator it = ... // instantiate the iterator
while (it.hasNext()) {
Object obj = it.next();
... // do something with obj
}
If the collection object (e.g. your set of objects) implements Iterable then you can use the new for loop syntax; e.g.
for (Object obj : yourSet) {
... // do something with obj
}
Of course, there are other ways to express this, but they all involve (somewhere) a loop of some kind to pull the objects from the iterator.
I want to have a reversed list view on a list (in a similar way than List#sublist provides a sublist view on a list). Is there some function which provides this functionality?
I don't want to make any sort of copy of the list nor modify the list.
It would be enough if I could get at least a reverse iterator on a list in this case though.
Also, I know how to implement this myself. I'm just asking if Java already provides something like this.
Demo implementation:
static <T> Iterable<T> iterableReverseList(final List<T> l) {
return new Iterable<T>() {
public Iterator<T> iterator() {
return new Iterator<T>() {
ListIterator<T> listIter = l.listIterator(l.size());
public boolean hasNext() { return listIter.hasPrevious(); }
public T next() { return listIter.previous(); }
public void remove() { listIter.remove(); }
};
}
};
}
I just have found out that some List implementations have descendingIterator() which is what I need. Though there is no general such implementation for List. Which is kind of strange because the implementation I have seen in LinkedList is general enough to work with any List.
Use the .clone() method on your List. It will return a shallow copy, meaning that it will contain pointers to the same objects, so you won't have to copy the list. Then just use Collections.
Ergo,
Collections.reverse(list.clone());
If you are using a List and don't have access to clone() you can use subList():
List<?> shallowCopy = list.subList(0, list.size());
Collections.reverse(shallowCopy);
Guava provides this: Lists.reverse(List)
List<String> letters = ImmutableList.of("a", "b", "c");
List<String> reverseView = Lists.reverse(letters);
System.out.println(reverseView); // [c, b, a]
Unlike Collections.reverse, this is purely a view... it doesn't alter the ordering of elements in the original list. Additionally, with an original list that is modifiable, changes to both the original list and the view are reflected in the other.
If i have understood correct then it is one line of code .It worked for me .
Collections.reverse(yourList);
Its not exactly elegant, but if you use List.listIterator(int index) you can get a bi-directional ListIterator to the end of the list:
//Assume List<String> foo;
ListIterator li = foo.listIterator(foo.size());
while (li.hasPrevious()) {
String curr = li.previous();
}
I use this:
public class ReversedView<E> extends AbstractList<E>{
public static <E> List<E> of(List<E> list) {
return new ReversedView<>(list);
}
private final List<E> backingList;
private ReversedView(List<E> backingList){
this.backingList = backingList;
}
#Override
public E get(int i) {
return backingList.get(backingList.size()-i-1);
}
#Override
public int size() {
return backingList.size();
}
}
like this:
ReversedView.of(backingList) // is a fully-fledged generic (but read-only) list
java.util.Deque has descendingIterator() - if your List is a Deque, you can use that.
Collections.reverse(nums) ... It actually reverse the order of the elements.
Below code should be much appreciated -
List<Integer> nums = new ArrayList<Integer>();
nums.add(61);
nums.add(42);
nums.add(83);
nums.add(94);
nums.add(15);
//Tosort the collections uncomment the below line
//Collections.sort(nums);
Collections.reverse(nums);
System.out.println(nums);
Output: 15,94,83,42,61
I know this is an old post but today I was looking for something like this. In the end I wrote the code myself:
private List reverseList(List myList) {
List invertedList = new ArrayList();
for (int i = myList.size() - 1; i >= 0; i--) {
invertedList.add(myList.get(i));
}
return invertedList;
}
Not recommended for long Lists, this is not optimized at all. It's kind of an easy solution for controlled scenarios (the Lists I handle have no more than 100 elements).
Hope it helps somebody.
You can also invert the position when you request an object:
Object obj = list.get(list.size() - 1 - position);
For small sized list we can create LinkedList and then can make use of descending iterator as:
List<String> stringList = new ArrayList<>(Arrays.asList("One", "Two", "Three"));
stringList.stream().collect(Collectors.toCollection(LinkedList::new))
.descendingIterator().
forEachRemaining(System.out::println); // Three, Two, One
System.out.println(stringList); // One, Two, Three
You can also do this:
static ArrayList<String> reverseReturn(ArrayList<String> alist)
{
if(alist==null || alist.isEmpty())
{
return null;
}
ArrayList<String> rlist = new ArrayList<>(alist);
Collections.reverse(rlist);
return rlist;
}
I am a newbie, I have a question.
I have a map. I have to loop through the map and build the iterator.
Example:
public Iterable<Test> getTests(Map<String, Test> testMap,
Set<String> strings)
{
//loop tru the set of strings and build iterator.
for(final String test1 : strings)
{
Test test = testMap.get(test1);
//build a iterator. not a list.
}
return iterator
}
How can I do this?
First of all, your method is returning an Iterable, not an Iterator. Map, Set, and List all implement Iterable, so it might be easier than you think.
Second, an Iterable is merely a class that has an iterator() method which returns an Iterator.
So I would simply build a List of the results and then return it. If you really want to return an Iterator, I would instead call iterator() on the list and return that.
Skipping over your Iterator/Iterable confusion (and Iterable is basically an Iterator factory... so you need to write an Iterator either way), I think you mean something like this:
Iterator<Test> getTests(final Map<String,Test> testMap, final Set<String> strings) {
return new Iterator<Test>() {
private final Iterator<String> keyIter = strings.iterator();
private String lastKey;
public boolean hasNext() { return keyIter.hasNext(); }
public Test next() { lastKey = keyIter.next(); return testMap.get(lastKey); }
public void remove() { testMap.remove(lastKey); }
};
}
And if you want to return an Iterable, well, that just has to be a factory for those:
Iterable<Test> getTests(final Map<String,Test> testMap, final Set<String> strings) {
return new Iterable<Test>() {
public Iterator<Test> iterator() {
return new Iterator<Test>() {
private final Iterator<String> keyIter = strings.iterator();
private String lastKey;
public boolean hasNext() { return keyIter.hasNext(); }
public Test next() { lastKey = keyIter.next(); return testMap.get(lastKey); }
public void remove() { testMap.remove(lastKey); }
};
}
};
}
For extra credit, you can parameterise this method itself and have a generic way of iterating over a selection from a map:
Map<String, Action> map;
Set<String> keys;
for (Action x : filterMap(map, keys)) {
}
Since Collection extends Iterable, the correct solution would be to add the tests to some sort of collection, like an ArrayList.
Collection<Test> tests = new ArrayList<Test>();
for (String key : strings) {
Test t = testMap.get(key);
if (t != null)
tests.add(t);
}
return tests;
If you want to really return Iterable simplest way is this
public Iterable<Test> getTests(Map<String, Test> testMap, Set<String> strings)
{
testMap = new HashMap<String, Test>(testMap);
testMap.keySet().retainAll(strings);
return testMap.values();
}
If you want to return an iterator, replace the last line with
return testMap.values().iterator();
If you don't care about modifications to the passed in map, skip the initial temp map construction.
EDIT:
removed use of clone on the Map interface which doesn't have it.
As a stab in the dark, what you may be looking for is Map.entrySet.iterator(). It allows you to iterate over the entries of the map.
Note: I know this is not an answer to the OP's question, but it's my guess at answering what they are actually looking for. If this guess turns out to be wrong, I'll delete this answer again to spare people the confusion.
An Iterable is something different from an Iterator. An Iterable is something you can iterate through, like a List. You use an Iterator for that. Your questions is not clear about what you want to return from getTests().
Your best shot would be to create an Iterable (like a List or Vector) and return that, or return its Iterator.