I was wondering if there was a way to reverse traverse a Iterable in Java.
Iterable<DataSnapshot> snapShotIterator = dataSnapshot.getChildren();
for (DataSnapshot doc : snapShotIterator) {
BlogPost blogPost = doc.getValue(BlogPost.class);
blog_list.add(blogPost);
}
Above is my code that I am trying to get to traverse in a reverse order, is there a reverse function for Iterables like there is for Collections?
Thanks in advance!
Hyungjun
You can use Android Studio replace with "For Loop" and then "Reverse it"
ArrayList<String> list = new ArrayList<>();
list.add("Hello");
list.add("World");
// Iterate forwards
for (String string : list) {
//
}
this is a normal iteration.
Now if you position yourself on top of the for statement and do alt-enter (on Linux/Windows, can't remember the macOS shortcut)... you get:
And then, if you do it again (alt-enter), you now get the option to reverse the loop:
Which looks like this:
for (int i = list.size() - 1; i >= 0; i--) {
String string = list.get(i);
}
Obviously, this doesn't consider you having an "Iterator" but you get the idea in case you want to iterate over collections directly, without resorting to the Iterator interface.
basically you can reverse the iterable by traversing it and storing it's value in a reverse list, then traverse that list,
you'll have to traverse the iterable at first to be able to do iterate in reverse order
you can use org.apache.commons.collections.iterators to do it without implementing yourself
ReverseListIterator reverseListIterator = new ReverseListIterator(list);
of course there are a lot of other libs you can use
more can be found here
Related
Its a very trivial question and related to coding Style and I am just asking to make my coding style more readable
Suppose I have a Collection like linkedList and an Array and I need to iterate over both simultaneously.
currently the best way I know is to get a iterator over list and define a index variable outside the iterator loop and increment the index variable simultaneously to access both next elements {list and array}. Please refer the example below
LinkedList<Integer> list = new LinkedList<Integer>();
Integer[] arr = new Array[25];
// lets suppose both have 25 elements.
// My Iteration method will be
int index =0;
for (Integer val : list) {
System.out.println(val);
System.out.println(arr[index++]);
}
so is it the only way or is there any other way I can perform this iteration in more readable and more relatable manner, where I don't have to take index variable separately.
I know it can be possible that array might have less or more elements than collection but I am only talking about the cases where they have equal and we need to iterate over Both of them.
PS : anybody can write a code that a computer can understand, actual challenge is to write code which humans can understand easily.
What you have is essentially fine: it's simple, and simple can be sufficient to make code readable.
The only thing I would caution about is the side effect of index++ inside arr[index++]: if, say, you want to use the same value multiple times in the loop body, you couldn't simply copy+paste.
Consider pulling out a variable as the first thing in the loop to store the "current" array element (which is essentially what the enhanced for loop does for the list element).
for (Integer val : list) {
Integer fromArr = arr[index++];
// ...
}
Just to point out an alternative without having a separate variable for the index, you can use ListIterator, which provides you with the index of the element.
// Assuming list and are have same number of elements.
for (ListIterator<Integer> it = list.listIterator();
it.hasNext();) {
// The ordering of these statements is important, because next() changes nextIndex().
Integer fromArr = arr[it.nextIndex()];
Integer val = it.next();
// ...
}
ListIterator is not an especially widely-used class, though; its use may in and of itself be confusing.
One of the downsides of the ListIterator approach is that you have to use the it correctly: you shouldn't touch it inside the loop (after getting the values), you have to put the statements in the right order, etc.
Another approach would be to create a library method analogous to Python's enumerate:
static <T> Iterable<Map.Entry<Integer, T>> enumerate(Iterable<? extends T> iterable) {
return () -> new Iterator<T>() {
int index = 0;
Iterator<? extends T> delegate = iterable.iterator();
#Override public boolean hasNext() { return delegate.hasNext(); }
#Override public Map.Entry<Integer, T> next() {
return new AbstractMap.SimpleEntry<>(index++, delegate.next());
}
};
}
This returns an iterable of map entries, where the key is the index and the value is the corresponding value.
You could then use this in an enhanced for loop:
for (Map.Entry<Integer, Integer> entry : enumerate(list)) {
Integer fromList = entry.getValue();
Integer fromArr = arr[entry.getKey()];
}
One option is to have 2 iterators, but I don't think it is any clearer:
for (Iterator<Integer> i1 = list.iterator(), i2 = Arrays.asList(arr).iterator();
i1.hasNext() && i2.hasNext();) {
System.out.println(i1.next());
System.out.println(i2.next());
}
But it is more robust in that it finishes at the shorter of the 2 collections.
I tried to simplify and handle size wise collections where both need not be of the same size. I believe this would work even if the sizes are not same and just one loop would suffice. Code snippet below:
LinkedList<Integer> list = new LinkedList<Integer>();
Integer[] arr = new Array[25];
int maxLength= Math.max(list.size(),arr.size());
//Looping over the lengthy collection( could be Linkedlist or arraylist)
for(int i=0;i<maxLength;i++){
if(list.size()>i)
System.out.println(list[i]);
if(arr.size()>i)
System.out.println(arr[i]);
}
Hope this helps! Thanks
I'm really good with VB and I have a project where I need to check an array. If the same item in an array exists twice or more it needs to be changed to an item that doesn't exist. Now I'm in a class where they're making us use Java for this project.
I was wondering what is the equivalent of a for each loop in Java? I checked the JavaDocs and it only had info for the regular for loop, I didn't notice any section that said anything about a for each loop.
It's more subtle in Java than VB. You can find the official docs in the Oracle documentation here (towards the bottom):
Java For Loops
The provided example is:
// Returns the sum of the elements of a
int sum(int[] a) {
int result = 0;
for (int i : a)
result += i;
return result;
}
Hope that helps. Be careful not to remove or add elements inside the loop or you will get a Concurrent Modification Exception.
try
String arr [] = // you decide how this gets initialized
for (String obj: arr) {
}
This is called "iterating over collections". An array can be implicitly converted to a collection, so you can iterate over an array in the same way, using the "enhanced for-loop".
List<String> names = new LinkedList<>();
// ... add some names to the collection
for(name:names) {
System.out.println(name);
}
I'm not sure if VB has collections - they are a big part of Java and I recommend you look into them.
Of course this changes a bit in Java 8, although you'll notice a collection is still the backbone of forEach().
List<String> names = new LinkedList<>();
// ... add some names to the collection
names.forEach(name -> System.out.println(name));
A for each loop (also known as the enhanced for loop) is as follows:
for (String name : names) {
// here, the loop will work over each element of 'names',
// with the variable name with which to access each element
// being 'name', and output it
System.out.println(name);
}
A normal for loop is as follows:
for (int i = 0; i < max; i++) {
// here, i will iterate until max, then the loop will stop.
// any array access here has to be done manually using i, which increments.
}
If insertion order from the names array is important, keep adding the objects to a LinkedHashSet<String>, then with either a for loop or enhanced for loop or iterator, go over your list of names and add each of them to the LinkedHashSet. If the add method, passing in your name, returns false, generate a new name and add that.
If insertion order is not important, use a HashSet<String> instead.
At the end, convert back to an array if it is important (String[] bla = map.toArray(new String[0])), or output the toString() of the map.
Ok, this is a proof-of-concept I have on my head that has been bugging me for a few days:
Let's say I have:
List<String> a = new ArrayList<String>();
a.add("foo");
a.add("buzz");
a.add("bazz");
a.add("bar");
for (int i = 0; i < a.size(); i++)
{
String str = a.get(i);
if (!str.equals("foo") || !str.equals("bar")) a.remove(str);
}
this would end up with the list ["foo", "bazz", "bar"] because it would read the string at index 1 ("buzz"), delete it, the string at index 2 ("bazz") would jump to index 1 and it would be bypassed without being verified.
What I came up with was:
List<String> a = new ArrayList<String>();
a.add("foo");
a.add("buzz");
a.add("bazz");
a.add("bar");
for (int i = 0; i < a.size(); i++)
{
String str = a.get(i);
boolean removed = false;
if (!str.equals("foo") || !str.equals("bar"))
{
a.remove(str);
removed = true;
}
if (removed) i--;
}
It should work this way (atleast it does in my head lol), but messing with for iterators is not really good practice.
Other way I thought would be creating a "removal list" and add items to that list that needed to be removed from list a, but that would be just plain resource waste.
So, what is the best practice to remove items from a list efficiently?
Use an Iterator instead and use Iterator#remove method:
for (Iterator<String> it = a.iterator(); it.hasNext(); ) {
String str = it.next();
if (!str.equals("foo") || !str.equals("bar")) {
it.remove();
}
}
From your question:
messing with for iterators is not really good practice
In fact, if you code oriented to interfaces and use List instead of ArrayList directly, using get method could become into navigating through all the collection to get the desired element (for example, if you have a List backed by a single linked list). So, the best practice here would be using iterators instead of using get.
what is the best practice to remove items from a list efficiently?
Not only for Lists, but for any Collection that supports Iterable, and assuming you don't have an index or some sort of key (like in a Map) to directly access to an element, the best way to remove an element would be using Iterator#remove.
You have three main choices:
Use an Iterator, since it has that handy remove method on it. :-)
Iterator<String> it = list.iterator();
while (it.hasNext()) {
if (/*...you want to remove `it.next()`...*/) {
it.remove();
}
}
Loop backward through the list, so that if you remove something, it doesn't matter for the next iteration. This also has the advantage of only calling list.size() once.
for (int index = list.size() - 1; index >= 0; --index) {
// ...check and optionally remove here...
}
Use a while loop instead, and only increment the index variable if you don't remove the item.
int index = 0;
while (index < list.size()) {
if (/*...you want to remove the item...*/) {
list.removeAt(index);
} else {
// Not removing, move to the next
++index;
}
}
Remember that unless you know you're dealing with an ArrayList, the cost of List#get(int) may be high (it may be a traversal). But if you know you're dealing with ArrayList (or similar), then...
Your first example will likely cause off-by-one errors, since once you remove an object your list's indexes will change. If you want to be quick about it, use an iterator or List's own .remove() function:
Iterator<String> itr = yourList.iterator();
while (itr.hasNext()) {
if ("foo".equals(itr.next()) {
itr.remove();
}
}
Or:
yourList.remove("foo");
yourList.removeAll("foo"); // removes all
ArrayList.retainAll has a "smart" implementation that does the right thing to be linear time. You can just use list.retainAll(Arrays.asList("foo", "bar")) and you'll get the fast implementation in that one line.
I want to iterate through some kind of list, checking if its elements meet a property, and if they don't deleting them from the array. What I've thought is something like this:
int index = 0;
for(int i = 0; i < list.size(); ++i) {
if(list.isProperty()) list.delete(index) //We delete the element at list[index]
else ++index;
}
Maybe those aren't the real methods of the list interface in java, but they're quite self-explanatory.
Is this a good approach? Which data structure would fit best if I have to run this operation many times? I don't think an arrayList would work as I'd have to be moving around elements each time I delete and I can't ensure the elements I'll remove are in the head or the tail of the list either.
You can achieve it using iterator.Without having concurrent modification exception.
Say your list consists of object A
List<A> list = new ArrayList<A>();
Iterator<A> iterator = list.iterator();
while (iterator.hasNext()) {
A current = iterator.next();
if(current.isProperty()) {
iterator.remove();;
}
}
You should remove an element from a List using an Iterator. You can use this with ArrayList.
List<YourDataType> yourList = new ArrayList<YourDataType>();
Iterator<YourDataType> it = yourList.iterator();
while (it.hasNext())
it.remove();
With this you can use if-else to specify the element, which should be removed.
This should give you some hints, why you should use an Iterator.
What is the best way to get value from java.util.Collection by index?
You shouldn't. a Collection avoids talking about indexes specifically because it might not make sense for the specific collection. For example, a List implies some form of ordering, but a Set does not.
Collection<String> myCollection = new HashSet<String>();
myCollection.add("Hello");
myCollection.add("World");
for (String elem : myCollection) {
System.out.println("elem = " + elem);
}
System.out.println("myCollection.toArray()[0] = " + myCollection.toArray()[0]);
gives me:
elem = World
elem = Hello
myCollection.toArray()[0] = World
whilst:
myCollection = new ArrayList<String>();
myCollection.add("Hello");
myCollection.add("World");
for (String elem : myCollection) {
System.out.println("elem = " + elem);
}
System.out.println("myCollection.toArray()[0] = " + myCollection.toArray()[0]);
gives me:
elem = Hello
elem = World
myCollection.toArray()[0] = Hello
Why do you want to do this? Could you not just iterate over the collection?
I agree with Matthew Flaschen's answer and just wanted to show examples of the options for the case you cannot switch to List (because a library returns you a Collection):
List list = new ArrayList(theCollection);
list.get(5);
Or
Object[] list2 = theCollection.toArray();
doSomethingWith(list[2]);
If you know what generics is I can provide samples for that too.
Edit: It's another question what the intent and semantics of the original collection is.
In general, there is no good way, as Collections are not guaranteed to have fixed indices. Yes, you can iterate through them, which is how toArray (and other functions) work. But the iteration order isn't necessarily fixed, and if you're trying to index into a general Collection, you're probably doing something wrong. It would make more sense to index into a List.
I agree that this is generally a bad idea. However, Commons Collections had a nice routine for getting the value by index if you really need to:
CollectionUtils.get(collection, index)
You must either wrap your collection in a list (new ArrayList(c)) or use c.toArray() since Collections have no notion of "index" or "order".
Convert the collection into an array by using function
Object[] toArray(Object[] a)
It would be just as convenient to simply convert your collection into a list whenever it updates. But if you are initializing, this will suffice:
for(String i : collectionlist){
arraylist.add(i);
whateverIntID = arraylist.indexOf(i);
}
Be open-minded.
you definitively want a List:
The List interface provides four methods for positional (indexed) access to list elements.
Lists (like Java arrays) are zero based.
Also
Note that these operations may execute in time proportional to the index value for some
implementations (the LinkedList class, for example). Thus, iterating over the elements in a > list is typically preferable to indexing through it if the caller does not know the
implementation.
If you need the index in order to modify your collection you should note that List provides a special ListIterator that allow you to get the index:
List<String> names = Arrays.asList("Davide", "Francesco", "Angelocola");
ListIterator<String> i = names.listIterator();
while (i.hasNext()) {
System.out.format("[%d] %s\n", i.nextIndex(), i.next());
}
use for each loop...
ArrayList<Character> al = new ArrayList<>();
String input="hello";
for (int i = 0; i < input.length(); i++){
al.add(input.charAt(i));
}
for (Character ch : al) {
System.Out.println(ch);
}
If your Collection is a List, simply cast it as a List and call get(final int index). Otherwise, it might make sense to consider finding the nth element in an ordered set, for example if it's a LinkedHashSet respecting insertion order (keep in mind that it's possible to create such an instance not respecting insertion order), you can use Collection.stream().skip(index).limit(1).findFirst().orElse(null).
You can get the value from collection using for-each loop or using iterator interface. For a Collection c
for (<ElementType> elem: c)
System.out.println(elem);
or Using Iterator Interface
Iterator it = c.iterator();
while (it.hasNext())
System.out.println(it.next());