I'm currently learning Java and I'm interested in learning how to use the list foreach method rather than using a manually constructed for loop. I suspect they can perform the same.
My current code looks like this:
while(!this.cards.isEmpty()) {
for(int i = 0; i < this.table.GetPlayerCount() && !this.cards.isEmpty(); i++) {
DealOneCardToPlayer(this.table.players.get(i) ,this.cards.get(0));
this.cards.remove(0);
}
}
I suspect that there is a way to use something like this:
this.cards.foreach() { do suff }
but I haven't quite been able to nail down the syntax... can someone give me a quick hand?
I think you can do it by iterating over the indexes of the cards:
IntStream.range(0, this.cards.size()).forEach(idx -> {
DealOneCardToPlayer(
this.table.players.get(idx % this.table.GetPlayerCount()),
this.cards.get(idx));
});
Although this doesn't remove the cards as you go; if you really need this.cards to be empty after:
this.cards.clear();
If you want to limit the number of cards dealt out (e.g. you want to deal N cards to each player), the easiest way is to extract a sublist, and then just apply the same method above:
List<Card> cardsToDeal = this.cards.subList(0, numCardsToDeal);
IntStream.range(0, cardsToDeal.size()).forEach(idx -> {
DealOneCardToPlayer(
this.table.players.get(idx % this.table.GetPlayerCount()),
cardsToDeal.get(idx));
});
cardsToDeal.clear();
You're talking about Java 8's Function API (and lambdas).
Essentially lambdas are a shorthand brethren to functions/methods, they have inputs and potentially return values. For the #forEach, it requests that you provide a function which accepts a T (Your list type), and returns nothing. This is known as a Consumer. The method then takes the Consumer you gave it, and calls it for each element on your list.
For equivalency, these are essentially the same thing as far as you're concerned when developing:
void someConsumerMethod(Card c) {
//lambda code block
}
(Card c) -> //lambda code block
this::someConsumerMethod //direct reference to the first method
An example would be:
this.cards.forEach(c -> {
System.out.println(c); //fully expanded
});
this.cards.forEach(c -> System.out.println(c)); //shorthand / one-liner
//or, since println already matches a Consumer<Object>, we can method reference it!
this.cards.forEach(System.out::println);
As for adapting your example, I wouldn't recommend modifying a collection while you iterate it (at least, not without using Iterator#remove). Andy Turner's answer already shows you how to use an application of IntStream to iterate the indexes you want.
What you are looking for is lambda expressions. The forEach method takes a functional interface (an interface with one abstract method), meaning it can be used as follows:
List<String> myList;
myList.forEach((String s) -> System.out.println(s));
Source: http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-QuickStart/index.html
You mean you want to use new Java 8 streams with your List.
So the syntax is like:
this.cards.stream().forEach(card -> {// do something here});
You can call stream() to access the method forEach().
Or directly with your List:
this.cards.forEach(...);
In my example I use the new Java 8 arrow functions that is a convenient way to avoids the boiler plate of the anonymous class (much an evolution).
You can pass a method to the forEach():
this.cards.stream().forEach(doSomethingWithMyCard);
You may keep track of the current player index, and iterate over the cards pack, to distribute it entirely :
int playerIndex = 0;
for(Card card : cards){
DealOneCardToPlayer(this.table.players.get(playerIndex) , card);
if(playerIndex == this.table.GetPlayerCount()-1)
playerIndex = 0;
else
playerIndex = playerIndex + 1;
}
If you only want to distribute one card per player, replace
if(playerIndex == this.table.GetPlayerCount()-1)
playerIndex = 0;
else
playerIndex = playerIndex + 1;
With :
if(playerIndex == this.table.GetPlayerCount()-1)
break;
Your example is not really suitable to be converted to a forEach call because you have all those extra conditions in there and stuff. You are also modifying the list in the for loop. Because of these reasons, you better stick with a for loop.
A forEach call can be used when you want to mutate the objects in a list, or you just want to access each item in the list.
The syntax looks like this:
list.forEach(item -> <insert the stuff you want to do to the item here>);
Here are some examples showing how to use forEach. I also provided the equivalent for loop:
// forEach
list.forEach(item -> item.setSomeProperty(1));
// for loop
for (int i = 0 ; i < list.size() ; i++) {
list.get(i).setSomeProperty(1);
}
// forEach
list.forEach(item -> item.doStuff());
// for loop
for (int i = 0 ; i < list.size() ; i++) {
list.get(i).doStuff()
}
// forEach
list.forEach(item -> System.out.println(item));
// for loop
for (int i = 0 ; i < list.size() ; i++) {
System.out.println(list.get(i));
}
Hopefully you can understand the syntax by looking at the above examples.
Note that the last example can be simplified to:
list.forEach(System.out::println);
We're basically telling it to call System.out::println on each item.
Related
Java 8 introduced Lambdas, which allow us to efficiently remove all elements from a List. The following removes all instances of 2 from myList.
List<Integer> myList;
...
myList.removeIf(x -> x==2);
If I wanted to remove N number of elements (in this case, three), I would use a for loop.
for (int i = 0; i < 3; i++) {
myList.remove(Integer.valueOf(2));
}
Is there a way to remove a specified number of elements from a List using Lambdas? If so, is it more efficient than the for loop code?
When you repeatedly call remove(Object) you get O(n²) time complexity from both, starting the search repeatedly from the beginning (applies to all List types) and from repeatedly copying the elements after the removed one, when the list is an ArrayList or similar.
The time complexity of the search can be avoided by using a dedicated search and remove loop, e.g. using an Iterator and its remove method. But the copying time complexity remains, unless you use removeIf and the list class overrides it with an appropriate implementation (as ArrayList does).
One way of utilizing this advantage for removing n matches would be
int n = 3;
int last = IntStream.range(0, myList.size())
.filter(ix -> myList.get(ix) == 2)
.limit(n)
.reduce((a,b) -> b)
.orElse(-1);
myList.subList(0, last + 1).removeIf(x -> x == 2);
It’s more complicated and for small lists, it will be more expensive. However, for really large lists where the time complexity matters, it will benefit from the O(n) time complexity.
Note that when the predicate is a simple match operation, you can also use, e.g. removeAll(Collections.singleton(2)) instead of removeIf(x -> x == 2).
Using lambdas:
Runnable runnable = () -> {
for (int i = 0; i < 3; i++) {
myList.remove(Integer.valueOf(2));
}
};
runnable.run();
Just kidding.
You can do something close to a for-loop:
IntStream.range(0,3).forEach(a-> integers.remove(Integer.valueOf(2)));
It should be equivalent to a for-loop in terms of performance.
A bit dirty, but requires just one pass:
public static <T extends Comparable<? super T>> List<T> removeFirstN(List<T> list, T t, int N) {
int[] a = {0};
return list.stream().filter(p -> !p.equals(t) || ++a[0] > N).collect(toList());
}
I have a vector of object and I need to compare them 1-by-1. That is:
for (Object o1 : list) {
for (Object o2 : list) {
//Do something with o1 and o2
}
}
Anyway using this approach I will compare any couple twice!
Using a "C" style approach, I would have done this:
for (i=0; i<n-1; i++) {
for (j=i+1; j<n; j++) {
//Do something with list[i] and list[j]
}
}
where n is the length of the list.
Is there a way to do this using for-each loop?
Addition
The usage of a for-each loop is not mandatory. Anyway, I'm concerned with performances issues. Does the for-each loop is faster than a simple for accessing index directly or not?
It is explicitly clear what your intent is with the C-like for loops - loop over every pair exactly once, so that the same pair with reversed members, e.g. (a, b) and (b, a) doesn't get processed again. That is what I would recommend; it works in Java just as well.
However, if you absolutely have to have the enhanced for loop, you can have the inner for loop operate over a sublist, with List's subList method, starting with the next element.
for (Object o1 : list) {
List<Object> subList = list.subList(list.indexOf(o1) + 1, list.size());
for (Object o2 : subList) {
//Do something with o1 and o2
}
}
The enhanced for loop is not appropriate in all situations. If you avoid using an index, just to use indexOf in the loop, your code will be less efficient (indexOf is a linear search) and non-idiomatic.
In my opinion, the best answer is to use the explicit indices.
for (i=0; i<n-1; i++) {
for (j=i+1; j<n; j++) {
// do something with list.get(i) and list.get(j)
}
}
One situation where you should avoid using get is if the List is a LinkedList, because get for a LinkedList is not a constant time operation. In this case I would do
List<Object> copy = new ArrayList<>(linkedList);
for (i=0; i<n-1; i++) {
for (j=i+1; j<n; j++) {
// do something with copy.get(i) and copy.get(j)
}
}
Assuming list is declared as List<Whatever>, you may achieve this behavior properly by using ListIterator rather than for-each loops:
ListIterator<Whatever> iteratorI = list.listIterator();
if (iteratorI.hasNext()) {
for (Whatever whateverI = iteratorI.next(); iteratorI.hasNext(); whateverI = iteratorI.next()) {
ListIterator<Whatever> iteratorJ = list.listIterator(iteratorI.nextIndex());
for (Whatever whateverJ = iteratorJ.next(); iteratorj.hasNext(); whateverJ = iteratorJ.next()) {
//do the comparison here...
}
}
}
The comments suggest you do it c-style or track an explicit index. Those are good suggestions. But if you insist on doing it with the new style for loop, there is a way:
for (Object o1 : list ) {
final int o1Index = list.indexOf(o1);
final int listSize = list.size();
for (Object o2 : list.subList(o1Index + 1, listSize)) {
//Do something with o1 and o2
}
}
The idea is that any o2 that comes before o1 in the list has already been processed, and you don't need to process o1 against itself. So you get a sublist consisting only of the elements following o1 and draw o2 from that sublist.
That will fail if any elements appear more than once in the list.
I've broken out o1Index and listSize for clarity, but in practice you'd probably in-line them.
Another option is to copy the original list and, before starting the inner loop, remove the front element each time. This properly accounts for duplicate elements, but takes more space.
final List<Object> newList = new ArrayList<>(list);
for (Object o1 : list) {
newList.remove(0);
for (Object o2 : newList) {
// Do something
}
}
You want performance?
Here you go!
The usage of a for-each loop is not mandatory
int s = list.size();
for(int i = 0; i < s-1; i++){
for(int n = i+1; n< s;n++){
if(list.get(i).equals(list.get(n))){
System.out.println("Duplicate");
}
}
}
You will never compare a combination twice.
Also to fully answer you question:
foreach does require more resources and reduces performance
To achieve the same result with foreach statement you'd create very much heap and slow the application down, also more instructions are processed by the CPU so you don't just loose memory but computing performance too.
Also try avoiding to call the size() method more than one time hence your list is not modified within this procedure. This also reduces CPU usage, but requires a very little bit more RAM (int s).
So your "C" style approach is almost optimal.
For ease i used java api calls, it also should be a ease to usw this example on your target framework.
EDIT: Improve performance even more by saving the list's size to reduce method calls.
This is a very specific case, comparison is just an operation of an infinity of other operations, other non commutative operations have a meaning for all combinations (this is just an example).
So there is no enhanced loop for such case.
I've inherited a bunch of code that makes extensive use of parallel arrays to store key/value pairs. It actually made sense to do it this way, but it's sort of awkward to write loops that iterate over these values. I really like the new Java foreach construct, but it does not seem like there is a way to iterate over parallel lists using this.
With a normal for loop, I can do this easily:
for (int i = 0; i < list1.length; ++i) {
doStuff(list1[i]);
doStuff(list2[i]);
}
But in my opinion this is not semantically pure, since we are not checking the bounds of list2 during iteration. Is there some clever syntax similar to the for-each that I can use with parallel lists?
I would use a Map myself. But taking you at your word that a pair of arrays makes sense in your case, how about a utility method that takes your two arrays and returns an Iterable wrapper?
Conceptually:
for (Pair<K,V> p : wrap(list1, list2)) {
doStuff(p.getKey());
doStuff(p.getValue());
}
The Iterable<Pair<K,V>> wrapper would hide the bounds checking.
From the official Oracle page on the enhanced for loop:
Finally, it is not usable for loops
that must iterate over multiple
collections in parallel. These
shortcomings were known by the
designers, who made a conscious
decision to go with a clean, simple
construct that would cover the great
majority of cases.
Basically, you're best off using the normal for loop.
If you're using these pairs of arrays to simulate a Map, you could always write a class that implements the Map interface with the two arrays; this could let you abstract away much of the looping.
Without looking at your code, I cannot tell you whether this option is the best way forward, but it is something you could consider.
This was a fun exercise. I created an object called ParallelList that takes a variable number of typed lists, and can iterate over the values at each index (returned as a list of values):
public class ParallelList<T> implements Iterable<List<T>> {
private final List<List<T>> lists;
public ParallelList(List<T>... lists) {
this.lists = new ArrayList<List<T>>(lists.length);
this.lists.addAll(Arrays.asList(lists));
}
public Iterator<List<T>> iterator() {
return new Iterator<List<T>>() {
private int loc = 0;
public boolean hasNext() {
boolean hasNext = false;
for (List<T> list : lists) {
hasNext |= (loc < list.size());
}
return hasNext;
}
public List<T> next() {
List<T> vals = new ArrayList<T>(lists.size());
for (int i=0; i<lists.size(); i++) {
vals.add(loc < lists.get(i).size() ? lists.get(i).get(loc) : null);
}
loc++;
return vals;
}
public void remove() {
for (List<T> list : lists) {
if (loc < list.size()) {
list.remove(loc);
}
}
}
};
}
}
Example usage:
List<Integer> list1 = Arrays.asList(new Integer[] {1, 2, 3, 4, 5});
List<Integer> list2 = Arrays.asList(new Integer[] {6, 7, 8});
ParallelList<Integer> list = new ParallelList<Integer>(list1, list2);
for (List<Integer> ints : list) {
System.out.println(String.format("%s, %s", ints.get(0), ints.get(1)));
}
Which would print out:
1, 6
2, 7
3, 8
4, null
5, null
This object supports lists of variable lengths, but clearly it could be modified to be more strict.
Unfortunately I couldn't get rid of one compiler warning on the ParallelList constructor: A generic array of List<Integer> is created for varargs parameters, so if anyone knows how to get rid of that, let me know :)
You can use a second constraint in your for loop:
for (int i = 0; i < list1.length && i < list2.length; ++i)
{
doStuff(list1[i]);
doStuff(list2[i]);
}//for
One of my preferred methods for traversing collections is the for-each loop, but as the oracle tutorial mentions, when dealing with parallel collections to use the iterator rather than the for-each.
The following was an answer by Martin v. Löwis in a similar post:
it1 = list1.iterator();
it2 = list2.iterator();
while(it1.hasNext() && it2.hasNext())
{
value1 = it1.next();
value2 = it2.next();
doStuff(value1);
doStuff(value2);
}//while
The advantage to the iterator is that it's generic so if you don't know what the collections are being used, use the iterator, otherwise if you know what your collections are then you know the length/size functions and so the regular for-loop with the additional constraint can be used here. (Note I'm being very plural in this post as an interesting possibility would be where the collections used are different e.g. one could be a List and the other an array for instance)
Hope this helped.
With Java 8, I use these to loop in the sexy way:
//parallel loop
public static <A, B> void loop(Collection<A> a, Collection<B> b, IntPredicate intPredicate, BiConsumer<A, B> biConsumer) {
Iterator<A> ait = a.iterator();
Iterator<B> bit = b.iterator();
if (ait.hasNext() && bit.hasNext()) {
for (int i = 0; intPredicate.test(i); i++) {
if (!ait.hasNext()) {
ait = a.iterator();
}
if (!bit.hasNext()) {
bit = b.iterator();
}
biConsumer.accept(ait.next(), bit.next());
}
}
}
//nest loop
public static <A, B> void loopNest(Collection<A> a, Collection<B> b, BiConsumer<A, B> biConsumer) {
for (A ai : a) {
for (B bi : b) {
biConsumer.accept(ai, bi);
}
}
}
Some example, with these 2 lists:
List<Integer> a = Arrays.asList(1, 2, 3);
List<String> b = Arrays.asList("a", "b", "c", "d");
Loop within min size of a and b:
loop(a, b, i -> i < Math.min(a.size(), b.size()), (x, y) -> {
System.out.println(x + " -> " + y);
});
Output:
1 -> a
2 -> b
3 -> c
Loop within max size of a and b (elements in shorter list will be cycled):
loop(a, b, i -> i < Math.max(a.size(), b.size()), (x, y) -> {
System.out.println(x + " -> " + y);
});
Output:
1 -> a
2 -> b
3 -> c
1 -> d
Loop n times ((elements will be cycled if n is bigger than sizes of lists)):
loop(a, b, i -> i < 5, (x, y) -> {
System.out.println(x + " -> " + y);
});
Output:
1 -> a
2 -> b
3 -> c
1 -> d
2 -> a
Loop forever:
loop(a, b, i -> true, (x, y) -> {
System.out.println(x + " -> " + y);
});
Apply to your situation:
loop(list1, list2, i -> i < Math.min(a.size(), b.size()), (e1, e2) -> {
doStuff(e1);
doStuff(e2);
});
Simple answer: No.
You want sexy iteration and Java byte code? Check out Scala:
Scala for loop over two lists simultaneously
Disclaimer: This is indeed a "use another language" answer. Trust me, I wish Java had sexy parallel iteration, but no one started developing in Java because they want sexy code.
ArrayIterator lets you avoid indexing, but you can’t use a for-each loop without writing a separate class or at least function. As #Alexei Blue remarks, official recommendation (at The Collection Interface) is: “Use Iterator instead of the for-each construct when you need to: … Iterate over multiple collections in parallel.”:
import static com.google.common.base.Preconditions.checkArgument;
import org.apache.commons.collections.iterators.ArrayIterator;
// …
checkArgument(array1.length == array2.length);
Iterator it1 = ArrayIterator(array1);
Iterator it2 = ArrayIterator(array2);
while (it1.hasNext()) {
doStuff(it1.next());
doOtherStuff(it2.next());
}
However:
Indexing is natural for arrays – an array is by definition something you index, and a numerical for loop, as in your original code, is perfectly natural and more direct.
Key-value pairs naturally form a Map, as #Isaac Truett remarks, so cleanest would be to create maps for all your parallel arrays (so this loop would only be in the factory function that creates the maps), though this would be inefficient if you just want to iterate over them. (Use Multimap if you need to support duplicates.)
If you have a lot of these, you could (partially) implement ParallelArrayMap<> (i.e., a map backed by parallel arrays), or maybe ParallelArrayHashMap<> (to add a HashMap if you want efficient lookup by key), and use that, which allows iteration in the original order. This is probably overkill though, but allows a sexy answer.
That is:
Map<T, U> map = new ParallelArrayMap<>(array1, array2);
for (Map.Entry<T, U> entry : map.entrySet()) {
doStuff(entry.getKey());
doOtherStuff(entry.getValue());
}
Philosophically, Java style is to have explicit, named types, implemented by classes. So when you say “[I have] parallel arrays [that] store key/value pairs.”, Java replies “Write a ParallelArrayMap class that implements Map (key/value pairs) and that has a constructor that takes parallel arrays, and then you can use entrySet to return a Set that you can iterate over, since Set implements Collection.” – make the structure explicit in a type, implemented by a class.
For iterating over two parallel collections or arrays, you want to iterate over a Iterable<Pair<T, U>>, which less explicit languages allow you to create with zip (which #Isaac Truett calls wrap). This is not idiomatic Java, however – what are the elements of the pair? See Java: How to write a zip function? What should be the return type? for an extensive discussion of how to write this in Java and why it’s discouraged.
This is exactly the stylistic tradeoff Java makes: you know exactly what type everything is, and you have to specify and implement it.
//Do you think I'm sexy?
if(list1.length == list2.length){
for (int i = 0; i < list1.length; ++i) {
doStuff(list1[i]);
doStuff(list2[i]);
}
}
In C++, I can use find_if with a predicate to find an element in a container. Is there something like that in Java? The contains method on collections uses equals and can not be parameterized.
You can use Predicate from Google Collections. Here is the tutorial and an example from it:
final Predicate<Car> expensiveCar = new Predicate<Car>() {
public boolean apply(Car car) {
return car.price > 50000;
}
}
List<Car> cars = Lists.newArrayList();
cars.add(new Car("Ford Taurus", 20000));
cars.add(new Car("Tesla", 90000));
cars.add(new Car("Toyota Camry", 25000));
cars.add(new Car("McClaren F1", 600000));
final List<Car> premiumCars =
Lists.immutableList(Iterables.filter(cars, expensiveCar));
You can also look at this thread: What is the best way to filter a Collection?
You can use CollectionUtils.select from Apache Commons.
For example, the following C++ code
bool isOdd (int i) {
return i % 2 != 0;
}
...
vector<int> myvector;
vector<int>::iterator it;
myvector.push_back(10);
myvector.push_back(25);
myvector.push_back(40);
myvector.push_back(55);
it = find_if (myvector.begin(), myvector.end(), isOdd);
cout << "The first odd value is " << *it << endl;
can be written in Java as,
List<Integer> myList = Arrays.asList(10, 25, 40, 55);
List<Integer> oddNums = (List<Integer>) CollectionUtils.select(myList,
new Predicate<Integer>() {
public boolean apply(Integer i) {
return i % 2 != 0;
}
}
);
System.out.println("The first odd value is "+oddNums.get(0));
Please note that, unlike in C++ example, this would create a new list of the elements satisfying the specified predicate.
EDIT :
As Matthew Flaschen has suggested in a comment below, CollectionUtils.find is even closer to what you need. So, with find, the above code can be rewritten as:
List<Integer> myList = Arrays.asList(10, 25, 40, 55);
Integer firstOdd = (Integer) CollectionUtils.find(myList,
new Predicate<Integer>() {
public boolean apply(Integer i) {
return i % 2 == 1;
}
}
);
System.out.println("The first odd value is "+firstOdd);
The problem is that using a method like find_if should make the code simpler to write and easier to read. However, IMHO Java does not lend itself to functional notation and most of the time it is clearer and simpler to just write a natural loop. i.e. the code is shorter and doesn't require knowledge of libraries most people don't use. If this functionality was built in and Java supported Closures (as
it appears Java 7 will) then using predicates and functional methods would make more sense.
One measure of complexity is to count the number of symbols (counting open/close brackets as one) Using this measure of complexity, most predicate based solutions have more symbols and are possibly more complex and difficult for developers to read/maintain.
In the example given by #Roman, there are 15 symbols. In the loop example, there are 10 symbols.
List<Car> premiumCars = new ArrayList();
for(Car car: cars)
if(car.price > 50000)
premiumCars.add(car);
In the example by #Mario Fuscom, there is 9 symbols, in the following example there is 9 symbols. However, no non-standard functions are required and anyone who knows Java can read/maintain it.
List peopleOver30 = new ArrayList();
for(Person person: people)
if(person.age > 30)
peopleOver30.add(person);
Taking the last example from #Rahul G - I hate Unicorns, there are 13 symbols. In the loop example, there are 8 symbols.
Integer firstOdd = null;
for(int i: myList)
if(i % 2 == 1) {
firstOdd = i;
break;
}
Functional programming may make more sense to you because that is your development background, but this doesn't mean it is the natural or simplest way to express this in Java. Java 7 may change this....
In Java 8, we have removeIf() which removes elements from the collections with certain Predicate. But we do not have something like find_if. But we can use stream API to achieve this.
List<Integer> list = Arrays.asList(20,35,50,654);
int result = list.stream().filter(i-> i%2!=0).findFirst().orElse(0).intValue();
System.out.println(result);
By using lambdaj you can easily filter a java collection in a very readable way. For example the following statement:
select(persons, having(on(Person.class).getAge(), greaterThan(30)));
selects all the persons in your list having more than 30 years.
I'm trying to replace an iterator-based loop over a Java list with a for-each statement, but the code uses at some point iterator.hasNext() to check if it reached the last element in the list.
Is there something similar for the for-each alternative?
for (Object current : objectList) {
if (last-element)
do-something-special
}
for-each is just syntactic sugar for iterator version and if you check compiled bytecode, then you'll notice that compilator actually change it into iterator version.
With a for-each form you can't check whether you'll have more elements or not.
Just stay with explicit iterator use if you need that feature.
In addition to Luno's answer:
Iterator<MyClass> it = myCollection.iterator();
while(it.hasNext()) {
MyClass myClass = it.next():
// do something with myClass
}
translates to:
for (MyClass myClass:myCollection) {
// do something with myClass
}
As others have said - this isn't possible.
Just remember that the foreach construct isn't the be-all and end-all. It was introduced to make the very common task of performing the same operations on each element of a collection simpler to denote.
In your case, you don't want to do exactly the same thing to each element - and thus a foreach loop is not the right tool for the job. Trying to "hack" it into doing this is silly, just use an explicit iterator in a classic for loop.
The foreach loop (or enhanced for loop) does not have facilities to keep track of which element is being iterated on at the moment. There is no way to find out which index of a Collection is being worked on, or whether there are more elements to be processed in an Iterable.
That said, one workaround that would work is to keep a reference to the object which is being iterated on at the moment in the foreach loop.
By keeping a reference of what it being worked on at the current iteration, one would be able to keep the reference once the foreach loop ends, and what is left in the variable will be the last element.
This workaround will only work if-and-only-if the last element is the only element which is needed.
For example:
String lastString = null;
for (String s : new String[] {"a", "b", "c"}) {
// Do something.
// Keep the reference to the current object being iterated on.
lastString = s;
}
System.out.println(lastString);
Output:
c
Unfortunately, the for each idiom does not allow you to check if an element is first or last in the list. This is a known limitation of the for each loop.
I suggest you just keep using the iterator.
If you can also check for the first element instead of the last one, for example if you're doing String concatenation, you could change to something like:
boolean first = true;
for (Element e : list) {
if (!first) {
//do optional operation
}
//do other stuff
first = false;
}
but I would prefer using the iterator.
If you want to stay with for-each maybe something like this:
if (objectList.indexOf(current)==objectList.size()-1) break;
int nElts = objectList.size();
int n = 0;
for (...) {
if (++n == nElts) ...
is the best I can think of.
There are two possible cases where you would like to do this.
You need to do something after the last element has been reached: in this case you just need to put your code outside of the loop.
for(Object item:theLinkedList){
}
System.out.println("something special")
you need to modify the last element in some way or use information related to the last element. In this case you should use the **LinkedList** to access the last element
for(Object item:theLinkedList){
}
Object last=theLinkedList.getLast();
System.out.println("last");
yes you can, here's how i would do it if you don't want to use the explicit iterator syntax:
for (Object current : objectList) {
if (objectList.getLast().equals(current))
do-something-special
}
In Addition to bayer you have to do it a bit different because there is no method getLast(). But instead of it you can use this objectList.size() - 1.
for (Object current : objectList) {
if (objectList.get(objectList.size() - 1).equals(current))
do-something-special
}
Just save loop repeat count, sample :
int loop = 0;
for(Item item : items) {
if(loop == 0) {
//Is First Item
}
if(loop != items.size()-1) {
//Has Next Item
}
if(loop == items.size()-1) {
//Is Last Item
}
//Must Be Last Statement
loop++;
}
It's similar to for(int i = 0; i < items.size(); i++) loop;
items.size() is used for lists and items.length for arrays;