11

I have the following problem. I have an integer position which starts at 1 and increments every time a specific person from a txt is found at a specific position in an xml. If I use the classic iteration with the foreach for (PersonMatchInfo pmi : personMatchInfo) it works, but my senior asked me to do with the Java 8 foreach and this type of iteration works only with final variables. How can I increment the integer in the new Java 8 loop? Thank you.

int position = 1;
personMatchInfo.forEach(pmi ->{

                    if (!stopwatch1.isStarted()) {
                        stopwatch1.start();
                    } else if (stopwatch1.isStarted()) {

                    }

                    if (pmi.getPersonName().equals(e.getValue())) {

                        positionMap.put(position, positionMap.get(position) + 1);
                        break;

                    } else {

                        position++;
                    }
                });
Uwe Allner
  • 3,399
  • 9
  • 35
  • 49
Tayfun Omer
  • 172
  • 1
  • 1
  • 7
  • 9
    by telling your senior: "that is not a reasonable request, it needlessly takes up time, is more complex and it is less readable. And I do not know how to do it because final blah blah blah, can you please help me!?" – luk2302 Oct 02 '17 at 08:41
  • He told me to use this type of loop because it "reduces" time a little and stuff. – Tayfun Omer Oct 02 '17 at 08:43
  • Possible duplicate of [Is there a concise way to iterate over a stream with indices in Java 8?](https://stackoverflow.com/questions/18552005/is-there-a-concise-way-to-iterate-over-a-stream-with-indices-in-java-8) – Fildor Oct 02 '17 at 08:43
  • Agreed, it's a very silly request from your senior. And if they don't believe you when you say so, you can show them this comment and at least you'll have the strength of the word of a few strangers on the Internet. – Jolta Oct 02 '17 at 08:43
  • Which is simply wrong, evidenced by this very conversation which definitely takes more time than leaving the already working code in place. – luk2302 Oct 02 '17 at 08:43
  • 1
    (It would not reduce the time consumed by the code - it would not perform better than a classical foreach loop.) – Jolta Oct 02 '17 at 08:44
  • 3
    Ask your senior if he is familiar with the term "premature optimization". – Fildor Oct 02 '17 at 08:45
  • 3
    @Fildor Can we add "K.I.S.S" while we're at it? –  Oct 02 '17 at 08:46
  • 1
    @Bilkokuya I think we could even find some more if we tried. – Fildor Oct 02 '17 at 08:46
  • I think stopwatch logic should not belong to the loop, place it outside, then it's not really clear what kind of map you are building (perhaps a unit test might be more self- explanatory next time). Also I would not just rely on what a senior says, just because Java 8 has streams does not mean they have to be used all the time, I am not sure it would be very performant. If you don't really want to do an imperative iteration try with a tail-recursion instead, it might work better – nuvio Oct 02 '17 at 12:44

4 Answers4

20

You can use AtomicInteger, and incrementAndGet method on it.

Other solution would be int[] position = new int[]{1};

and incrementing position[0]++;

b4hand
  • 9,550
  • 4
  • 44
  • 49
mlecz
  • 985
  • 11
  • 19
2

You can use a static variable :

public class Poubelle {

    private static int position = 1;

    public static void setPosition (List<PersonMatchInfo> listPersonMatchInfo) {

          listPersonMatchInfo.forEach(pmi -> {
          pmi.setPosition(position++);
        });
    }
}
Nicolas
  • 69
  • 3
  • Ironically, using a static int is what worked for me. I had a pair of nested lambda functions, and I needed to pass on the count of the inner lambda function into its contents. Since the outer lambda function needed to re-set the variable to zero every time it ticked over, I just did a `position = 0;` (to use your example) before the inner lambda function. Haven’t yet tested, but intellisense is not having a hissy fit. – René Kåbis Apr 01 '19 at 20:39
0

I think you senior is asking you to use streams for collections. Then use collection.stream.filter.count based on your logic that will produce a long as the value and use it.

  • 2
    no the downvoter, but that sounds like an utter abuse of the `filter` method and only works by coincidence. – luk2302 Oct 02 '17 at 08:45
  • Thanks bro for your answer – Mark_ZuckerBerg Oct 02 '17 at 08:49
  • I was initially thinking the same as Mark, and I think `map` `filter` `count` it's a perfectly valid case for counting instead of modifying a global state counter although I read the question again and I don't think a `count` operation is needed here as this is building a map with positions. – nuvio Oct 02 '17 at 12:40
0

I know it is late, so I will just put it out here for future seekers. Here is how you can do it in a very simple way :

use indexOf(Object O) property of collections

StringBuffer messageBody = new StringBuffer();    
List<VipObj> listOfAllVips = getResponse();
    listOfAllVipsLocal.forEach(vip -> {
                            messageBody.append("\n\t" + (listOfAllVipsLocal.indexOf(vip) + 1) + ". " + vip.getBaseUrl() + "\n");
                        });
Pranay Nailwal
  • 483
  • 6
  • 13