Elegant way to do "downward" iterations with iterators - java

For example, for a list {1,2,3,4}, I must compare the pairs (1,2), (1,3), (1,4), (2,3), (2,4), (3,4). The way with normal for loops is:
for(i=0 ; i<list.size() ; i++){
for(j=i+1 ; j<list.size() ; j++){
//do stuff with list[i] and list[j];
}
}
Can I do something like this with iterators (see below)?
for (int i : list){
for(int j : [list after index i]){
//do stuff with list[i] and list[j];
}
}

Maybe not that elegant, but possible:
int lastIndex = list.size()-1;
for (Object i : list) {
for (Object j : list.sublist(list.indexOf(i), list.size()-1)) {
// do what has to be done
}
}

Since the index of the items is clearly important here, I think you should stick with the old index-based for loop in this case. It might not be quite as pretty, but it will be explicit.
If you're doing this a lot you could encapsulate the code in a method and pass it a method to invoke per-pair.

This still uses nested loops, but uses a ListIterator instead.
A ListIterator can be obtained through the listIterator(idx) method of the List interface. Its not really more elegant than the for loop but might perform better if the list is not randomly accessible, for example a LinkedList.
for (ListIterator i=list.listIterator(); i.hasNext(); ) {
Object a = i.next();
for (Iterator j=list.listIterator(i.previousIndex()); j.hasNext(); ) {
Object b = j.next();
}
}

You can implement your own Iterator to do this. You'll also have to create a simple wrapper objects to let you return two items at once (it is very annoying that there is no tuple type built in to Java!).
Simply by implementing the Iterator however will not let you use it directly in a for loop. You'll have to do something like this instead:
Iterator<MyPairObject> iterator = new MyIterator(list);
while (iterator.hasNext()) {
...
}
However, if you subclass the list class you're using you can override the iterator() method and return your own iterator - then you'll be able to use your custom list class and it's iterator directly in a for loop.

Related

Iterate through an list of objects and run a function for each - Java

I'm wondering for the simplest method for how to run a specific function for each object in an array (or other list type)
My goal is to be able create a list of objects, and have each object run a specific function as it passes through the iterator.
I've tried a for loop on an arraylist
for (int i = 0; i < testList.size(); i++)
{
this = textList.get(i);
this.exampleFunction();
}
But this gives me a 'Variable expected' error
Assuming you're using Java 8+, and you have a Collection<TypeInList> you could call Collection.stream() and do a forEach on that. Like,
testList.stream().forEach(TypeInList::function);
Your current approach is trying to do things with this that cannot be done. It could be fixed like,
for (int i = 0; i < testList.size(); i++)
{
TypeInList that = testList.get(i); // this is a reserved word.
that.function();
}
or
for (TypeInList x : testList) {
x.function();
}
There are multiple ways to iterate through a list, but the easiest I personally find is like this:
Assuming that your list contains String objects e.g.:
List<String> list = new ArrayList();
list.add("Hello");
list.add("World");
for(String current : list){
System.out.println(current);
}
The loop will iterate twice, and console will output the following:
Hello
World
This approach doesn't rely on indexes (as how you're using it in your question), as such I find it easy to use for iterating through a single list.
However the disadvantage is that if you have 2 separate lists that you would like to iterate through, the lack of indexes makes it a bit more complicated. The easier approach for iterating through multiple lists would be using the traditional approach, something like this:
for(int i=0; i<list.size(); i++){
int x = list1.get(i);
int y = list2.get(i);
}
As such your use-case really determines the ideal method you can adopt.

Removing values in an arraylist that DO NOT match a value

I am having some trouble with removing values that do not match a given value. At the moment I am copying over values to a new list and trying to clear the original list - but this is inefficient.
This is my code:
int size = list.size();
ArrayList<String> newList;
int count = 0;
newList = new ArrayList<>();
for (int i=0; i<list.size(); i++){
if(list.get(i).getForename().equals(forename)){
newList.add(i, list);
}
}
list.clear();
Is there a way where I can just remove an item in the arraylist if it does NOT match the name?
EDIT:
It works but then I might need a copy, as if I select a another name from the dropdown it will be referring to the old one
Thanks
A first thought would be to iterate on the list and as soon as you find an item not matching the value, you remove it. But it will create a Concurrent modification exception, as you iterate on list while trying to remove elements in it.
An other, still not efficient would be to iterate on the list, keep track of the indexes to remove, and after iterating on the list, remove them.
ArrayList<Integer> indexList = new ArrayList<Integer>();
for(int i = 0; i<list.size(); i++){
if(!list.get(i).getForename().equals(forename)){
indexList.add(i);
}
for(Integer index : indexList){
list.remove(index);
}
indexList.clear();
Please not that this is not really efficient too, but maybe you were looking for a way to delete from the same list.
A simple solution is
while (list.contains(value)) {
list.remove(list.indexOf(value));
}
Depending on what you want, you might want to use streams instead (seems to be what you actually want, since you don't really seem to want to delete elements in your list):
newList = list.stream()
.filter(e -> getForename().equals(forename))
.collect(Collectors.toList());
or to perform your action what you might want to do:
list.stream()
.filter(e -> getForename().equals(forename))
.forEach(person -> doStuff(person));
Another way would be using iterators to avoid conflicts with modifications during iteration:
ListIterator iterator = list.listIterator();
while(iterator.hasNext()){
if(!iterator.getNext().getForename().equals(forename))
iterator.remove();
}
EDIT: Since OP can't use lambdas and streams (because of Java-version), here is what nearly happens for the second stream (the forEach). I am not using the proper interfaces, since OP can't do so either. The difference to streams is, that they also might split this into several threads and hence would be faster (especially on multi-core processors and big lists):
interface Consumer<T>{ //this is normally given by the JAVA 8 API (which has one more default method)
void accept(T t);
}
Consumer<YourObject> doIt = new Consumer<YourObject>(){ //This is what the lambda expression actually does
#Override
public void accept(YourObject e) {
doStuff(e);
}
};
for(YourObject element : list){ //since JAVA 1.5. Alternativ your old for-loop with element=list.get(i);
if(!element.getForename().equals(forename)) //the filter written in easy
continue;
doIt.accept(element); //You could also use a method or expressions instead in this context.
//doStuff(element); //What actually the upper stream does.
}
You might want to look at the oracle tutorial (this chapter) to get a feeling, when this design is appropriate https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html (I have a strong feeling, you might want to use it).
Assuming your List contains String objects the following should be what you are looking for:
for (Iterator<String> it = list.iterator(); it.hasNext()){
String foreName = it.next();
if(forName != null && foreName.equals(forename)){
it.remove();
}
}
try
for (int i=0; i<list.size();){
if(!list.get(i).getForename().equals(forename)){
list.remove(i);
}
else {
i++;
}
}

Can I subclass "standard" arraylist iterator?

I need to iterate all the elements of ArrayList except the last one. So I want to create such iterator. But I don't what to implement the whole iterator, I need to override only the hasNext() method, so I would like to subclass a "standard" iterator. Is there any way to do that?
I think the better way to do that rather than overriding the default iterator is to iterate the ArrayList on your own. An ArrayListhas a couple of method defined that can help you accomplish the task: get(int) and size().
Everything you have to do is to get the total number of elements in the ArrayList(with size()) and then loop through the elements accessing each element directly in each iteration using the get() method. Your code would look something like this:
for(int i = 0; i < myList.size() - 1; i++){
element = myList.get(i);
//do something
}
Now with this principle in mind, you may create your own class to iterate the ArrayList.
It would be odd to modify the iterator to perform this traversal. The obvious thing to do is to write the "algorithm" as you want it:
public static <T> void eachExceptLast(List<? extends T> list, Operation<T> op) {
Iterator<T> iter = list.iterator();
if (!iter.hasNext()) {
return;
}
T item = iter.next();
while (iter.hasNext()) {
op.run(item);
item = iter.next();
}
}
(Or use an index assuming a RandomAccess list.)
However, there's a much better way of doing this. list.subList(0, list.size()-1) (for a non-empty list) will return a view of the original list less the last element. It doesn't do a copy, and you can even use Iterator.remove.
You can create a class that implements either the Iterator or ListIterator interfaces and then override the hasNext() method .

Should we avoid hasNext() call in an Iterator?

Is it advisable not to use iterator.hasNext() in looping over an iterator?
For example I would like to set value obj to each element of a list. I could use the following code or make it more readable by using hasNext() in a loop.
int size = list.size();
ListIterator<? super T> itr = list.listIterator();
for (int i=0; i<size; i++) {
itr.next();
itr.set(obj);
}
Instead of these lines I could write my code like the following.
for (ListIterator<? super T> itr = list.listIterator(); itr.hasNext(); ) {
itr.next();
itr.set(obj);
}
Is it advisable not to use iterator.hasNext() in looping over an iterator?
Um, no. hasNext is the standard way you iterate with an iterator. That's what the enhanced-for statement does behind the scenes for an iterable, for example.
Having said that, your code is already ListIterator-specific, as you're using ListIterator.set - so your second block of code won't actually compile at the moment. Even if it did, it wouldn't work, as you still need to call next(). This would work though:
for (ListIterator<? super T> itr = list.listIterator(); itr.hasNext(); ) {
itr.next();
itr.set(obj);
}
Well, when NetBeans refactor you for-each loop to use of iterators, they do it in following way.
for-each:
for (T object : list) {
}
iterator pattern:
for (Iterator<T> it = list.iterator(); it.hasNext();) {
T object = it.next();
}
I think it is totally okay to use hasNext() on iterator while iterating.
There is no such recommendation not to use hasNext.
The Iterator API list has just three methods, add, remove and hasNext
Also from clean code the second approach looks far better then the first one.
When using an iterator, you should always call the hasNext() method. Otherwise, you may run into a NoSuchElementException when calling the next() method.
Of course, you should use hasNext(), but only for iterating over a collection, not for populating the collection. To fill the collection, work on the collection itself, not on it's iterator and to read from the collection use the for loop as described by #JMelnik.
Fill the collection
Collection<MyObject> list = ...;
while (something) {
list.add(myObject);
}
Read the collection
for (MyObject myObject : list) {
...
}

Java: Best way to iterate through a Collection (here ArrayList)

Today I was happily coding away when I got to a piece of code I already used hundreds of times:
Iterating through a Collection (here ArrayList)
For some reason, I actually looked at the autocompletion options of Eclipse and it got me wondering:
What cases are the following loops better to use than the others?
The classic array index loop:
for (int i = 0; i < collection.length; i++) {
type array_element = collection.get(index);
}
The Iterator hasNext()/next():
for (Iterator iterator = collection.iterator(); iterator.hasNext();) {
type type = (type) iterator.next();
}
And my favorite because its so simple to write:
for (iterable_type iterable_element : collection) {
}
The first one is useful when you need the index of the element as well. This is basically equivalent to the other two variants for ArrayLists, but will be really slow if you use a LinkedList.
The second one is useful when you don't need the index of the element but might need to remove the elements as you iterate. But this has the disadvantage of being a little too verbose IMO.
The third version is my preferred choice as well. It is short and works for all cases where you do not need any indexes or the underlying iterator (i.e. you are only accessing elements, not removing them or modifying the Collection in any way - which is the most common case).
All of them have there own uses:
If you have an iterable and need to traverse unconditionally to all of them:
for (iterable_type iterable_element : collection)
If you have an iterable but need to conditionally traverse:
for (Iterator iterator = collection.iterator(); iterator.hasNext();)
If data-structure does not implement iterable:
for (int i = 0; i < collection.length; i++)
There is additionally collections’ stream() util with Java 8
collection.forEach((temp) -> {
System.out.println(temp);
});
or
collection.forEach(System.out::println);
More information about Java 8 stream and collections for wonderers link
None of them are "better" than the others. The third is, to me, more readable, but to someone who doesn't use foreaches it might look odd (they might prefer the first). All 3 are pretty clear to anyone who understands Java, so pick whichever makes you feel better about the code.
The first one is the most basic, so it's the most universal pattern (works for arrays, all iterables that I can think of). That's the only difference I can think of. In more complicated cases (e.g. you need to have access to the current index, or you need to filter the list), the first and second cases might make more sense, respectively. For the simple case (iterable object, no special requirements), the third seems the cleanest.
The first option is better performance wise (As ArrayList implement RandomAccess interface). As per the java doc, a List implementation should implement RandomAccess interface if, for typical instances of the class, this loop:
for (int i=0, n=list.size(); i < n; i++)
list.get(i);
runs faster than this loop:
for (Iterator i=list.iterator(); i.hasNext(); )
i.next();
I hope it helps.
First option would be slow for sequential access lists.
Here is an example
Query query = em.createQuery("from Student");
java.util.List list = query.getResultList();
for (int i = 0; i < list.size(); i++)
{
student = (Student) list.get(i);
System.out.println(student.id + " " + student.age + " " + student.name + " " + student.prenom);
}

Categories