2

I need to write a Lambda function which can auto increment counter value. for example- my counter value is 0. Then, i execute lambda expression which shall increment counter value to 1 , set value 1 to counter and return this counter value (1) from lambda expression. Then, next time, when I call lambda expression , lambda should increment counter value to 2, and return value (2) from lambda. how to write such kind of lambda. I am new to lambda programming. please excuse me if I have ask pretty simple and straight forward question. Thanks in advance. Please help.

1

5 Answers 5

3
public static void main(String args[]) {

  //with type declaration
  MathOperation incrementCounter = (int a) -> a++;

  //with out type declaration
  MathOperation incrementCounter = a -> a++;

  //with return statement along with curly braces
  MathOperation incrementCounter = (int a) -> { return a++; };

  //without return statement and without curly braces
  MathOperation division = (int a) -> a++;

  System.out.println("Increment" + tester.operate(10, incrementCounter));

interface MathOperation {
  int operation(int a);
}

private int operate(int a, MathOperation mathOperation) {
  return mathOperation.operation(a);
}
}
Sign up to request clarification or add additional context in comments.

Comments

1

I don't think you can do that simply in a lambda expression, but you can use the anonymous class notation:

        Function<String,Integer> fct = new Function<String,Integer>() {
            int counter = 0;
            @Override
            public Integer apply(String t) {
                // ...
                return ++counter;
            }
        };

Comments

1

One thing to note, it is tempting to use lamda with Stream and when we work with Stream, it is easy to add a .parallel call to use multithreading. This adds some concurrencies problem.

One good thing is that could be solved using a class that could also help you with your task, AtomicInteger provide a method to increment AtomicInteger.incAndGet or to add AtomicInteger.addAndGet

This could be used as a method reference like this :

final int SIZE = 10_000;
AtomicInteger cnt = new AtomicInteger();
IntStream.range(0,  SIZE)
    .parallel().map(i -> 1)
    .forEach(cnt::addAndGet);

This is not the most interesting code, but this will increment using a synchronized counter, preventing the problems. I have use an equivalent code using a simple counter with an int for the comparison and on almost each tries, it fails.

Here is a quick code to prove the concept. It is a simple loop that will try 100 times each test and output in the console if there is a problem.

import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class Main {

    int cntInt;
    AtomicInteger cntAtom;

    final int SIZE = 10_000;
    final int TRIES = 1_000;

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Main().testInt();
        }
        for (int i = 0; i < 100; i++) {
            new Main().testAtomic();
        }
    }

    public void testInt(){

        int testCount = 0;
        do{
            cntInt = 0;
            testCount++;
            IntStream.range(0,  SIZE)
                .parallel().map(i -> 1)
                .forEach(i -> cntInt += i);
        }while(cntInt == SIZE && testCount < TRIES);
        if(cntInt != SIZE ){
            System.out.format("INTEGER Run: %d, Value: %d, Expected: %d%n", testCount, cntInt, SIZE);
        }
    }

    public void testAtomic(){
        int testCount = 0;
        do{
            cntAtom = new AtomicInteger();
            testCount++;
            IntStream.range(0,  SIZE)
                .parallel().map(i -> 1)
                .forEach(cntAtom::addAndGet);
        }while(cntAtom.get() == SIZE&& testCount < TRIES);
        if(cntAtom.get() != SIZE ){
            System.out.format("ATOMIC Run: %d. Value: %dm Expected: %d%n", testCount, cntAtom.get(), SIZE);
        }
    }
}

Some times, the INTEGER can run quite some time without any issues but you will notice that using an the AtomicInteger and the synchronize approach is safer.

Comments

0

It sounds like you are trying to do 2 things use a lambda and also create an increment solution. I would suggest separating the issues and ask why you need a lambda for the incrementer solution. The below is a solution with a lambda but it is hard for me to believe that I would ever write something like this in the real world.

interface Thing{
    public int increment();
}

public class Lambda {

    private static Integer counter = 0;

    /**
     *
     */
    public static Integer testingLambda() {
        Thing thing = () -> ++counter;
        return thing.increment();
    }
}

I would probably go for something like this instead...

public class Lambda {

private static int counter = 0;

private Lambda() {

}

public static void increment() {
    counter++;
}

public static int getCounter() {
    return counter;
}

Comments

0

This is the simplest lambda form which can auto-increment the value of a counter. The counter is initialized with 0. Each call of count.getAsInt() returns the current counter value and increments the counter afterwards (post-incremented). So the counter in the example returns 0, 1, 2….
With ++counter[0] it would be 1, 2, 3….

int[] counter = new int[] { 0 };
IntSupplier count = () -> counter[0]++;

count.getAsInt();   // returns 0, 1, 2…

1 Comment

While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.