77

Supposing that I have some foreach loop like this:

Set<String> names = new HashSet<>();
//some code
for (String name: names) {
     //some code
}

Is there a way to check inside foreach that the actual name is the last one in Set without a counter? I didn't found here some question like this.

ℛɑƒæĿᴿᴹᴿ
  • 4,983
  • 4
  • 38
  • 58
mhery
  • 2,097
  • 4
  • 26
  • 35
  • 5
    No, there is no such method on the Set interface. That abstraction doesn't imply an order, only that it's a Collection where every element is unique. – duffymo Jan 11 '17 at 12:35
  • Without counter you simply can't do it in java. – abbath Jan 11 '17 at 12:36
  • pls tell, what do you want to do if you know the current element is the last. Keep in mind, that the for each on `HashSet` won't keep the order. – Kent Jan 11 '17 at 12:37
  • Also, be aware that Set does not provide ordering guarantees. The last element you added might not be the last element in the iteration. – Bene Jan 11 '17 at 12:37
  • The important question is why do you need to do this. In many, perhaps most, cases, you can modify your algorithm slightly so that it's not necessary to know inside the loop that you're on the last iteration. – Jim Mischel Jan 11 '17 at 16:41

10 Answers10

79

For simplicity and understandability, imo, would do:

Set<String> names = new HashSet<>();
Iterator<String> iterator = names.iterator();
    while (iterator.hasNext()) {
        String name = iterator.next();
        //Do stuff
        if (!iterator.hasNext()) {
            //last name 
        }
     }

Also, it depends on what you're trying to achieve. Let's say you are implementing the common use case of separating each name by coma, but not add an empty coma at the end:

Set<String> names = new HashSet<>();
names.add("Joao");
names.add("Pereira");

//if the result should be Joao, Pereira then something like this may work
String result = names.stream().collect(Collectors.joining(", "));
luk4
  • 7
  • 3
Joao Pereira
  • 2,454
  • 4
  • 27
  • 35
41

Other answears are completely adequate, just adding this solution for the given question.

Set<String> names = new HashSet<>();

   //some code
   int i = 0;

for (String name: names) {
    if(i++ == names.size() - 1){
        // Last iteration
    }
   //some code

}
Edu G
  • 1,030
  • 9
  • 23
  • 1
    Thanks. Nice solution for the for each loop to check the last iteration. Although it's very similar to just using a for loop with an iterator. Still, nice solution! – NiallMitch14 Nov 07 '17 at 19:23
  • 15
    I'd adjust to `if(++i == names.size())`, which simply adds one to i before evaluating, meaning we can check directly against size of set, without that -1 – jumps4fun Sep 03 '18 at 10:13
28

There isn't, take a look at How does the Java 'for each' loop work?

You must change your loop to use an iterator explicitly or an int counter.

Community
  • 1
  • 1
Lazar Petrovic
  • 537
  • 3
  • 8
4

If you are working with a complex object and not just a plain list/set the below code might help. Just adding a map function to actually get the desired string before you collect.

String result = violations.stream().map(e->e.getMessage()).collect(Collectors.joining(", "));
Manoj G
  • 63
  • 5
3

Yes, there is a way to check it inside of foreach, by use of a counter:

Set<String> names = new HashSet<>();

int i = names.size() - 1;
for (String name: names) {
    if (i-- == 0) {
        // some code for last name
    }
    //some code
}

Consider, names.size() is called only one time outside of the loop. This makes the loop faster than processing it multiple times within the loop.

gotwo
  • 663
  • 8
  • 16
0

There is no build in method to check if the current element is also the last element. Besides that you are using a HashSet which does not guarantee the return order. Even if you want to check it e.g. with an index i the last element could always be a different one.

Murat Karagöz
  • 35,401
  • 16
  • 78
  • 107
0

A Set does not guaranty order over of items within it. You may loop through the Set once and retrieve "abc" as the "last item" and the next time you may find that "hij" is the "last item" in the Set.

That being said, if you are not concerned about order and you just want to know what the arbitrary "last item" is when observing the Set at that current moment, there is not built in way to do this. You would have to make use of a counter.

CraigR8806
  • 1,584
  • 13
  • 21
0

.map(String::toString) from the answer above is redundant, because HashSet already contains String values. Do not use Set to concatenate strings because the order is not assured.

List<String> nameList = Arrays.asList("Michael", "Kate", "Tom");
String result = nameList.stream().collect(Collectors.joining(", "));
luk4
  • 7
  • 3
0

There is an easy way you can do this throw one condition. consider this is your array:

int odd[] = {1,3,5,7,9,11};

and you want to print it all in one line with " - " hyphen between them except the last one.

for(int aa:odd) {
    System.out.print(aa);
            
    if(odd[odd.length - 1] != aa)
        System.out.print(" - ");
}

this condition

if( odd[odd.length - 1] != aa )

will check if you aren't in the last element so you can still add " - ", otherwise you will not add it.

Chandan
  • 11,465
  • 1
  • 6
  • 25
  • Welcome to the stackoverflow community! The original poster's scenario is that you have a Set in place of an array. The proposed solution in this answer only works for arrays it seems. – Hermann.Gruber Dec 18 '20 at 13:28
  • Welcome to the stackoverflow community thank you for contributing, it would be good if you can `format` your code with `4 spaces` instead of `tabs` or `spaces more than 4` and you can create `code block` using 3 tilde for `code section` that way you don't have to add 4 spaces in every line that you want to convert or add to `code block` for more markdown info you can look help link which will appear near answer input – Chandan Dec 18 '20 at 14:00
0
    List<String> list = Arrays.asList("1", "2", "3");
    for (String each : list) {
        if (list.indexOf(each) == (list.size() - 1)) {
            System.out.println("last loop");
        }
    }

Note: Set is NOT an ordered collection.

Chhorn Elit
  • 5,038
  • 1
  • 12
  • 14