Question: I am in the middle of solving various puzzles. Once again, the thought occurred to me about simplification with use of functional programming.

The problem to solve is : *Given an array of integers arr, a lucky integer is an integer which has a frequency in the array equal to its value.
Return a lucky integer in the array. If there are multiple lucky integers return the largest of them. If there is no lucky integer return -1.* .

I find my solution here cumbersome and complex, is there an easier way to breakdown this problem? (perhaps using lambda's)

```
        import java.util.*;

        public class FindLucky {

            public static int findLucky(int[] arr) {
                Map<Integer, Integer> map = new HashMap<>();
                Set<Integer> set = new TreeSet<>();
                for (Integer i : arr) {
                    if (map.containsKey(i)) {
                        map.replace(i, map.get(i) + 1);
                    } else {
                        map.put(i, 1);
                    }
                }

                for (Integer key : map.keySet()) {
                    if (key == map.get(key)) {
                        set.add(key);
                    }
                }

                if (set.size() < 1) {
                    return -1;
                }

                return Collections.max(set);
            }

                public static void main(String... args) {
                    findLucky(new int[]{1, 2, 2, 3, 3, 3});
                    findLucky(new int[]{2, 2, 2, 3, 3});
                    findLucky(new int[]{5});
                }
        }

```

Answer: 
Stream-based solution may look as follows:

```
static int findLucky(int[] arr) {
    return Arrays.stream(arr)
            .boxed() // convert to Integer
            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())) // group by number, count frequencies
            .entrySet().stream()
            .filter(e -> e.getKey().intValue() == e.getValue().intValue()) // select lucky candidates
            .mapToInt(e -> e.getKey().intValue())
            .max().orElse(-1);
}

```

The complexity of this solution is linear.
> 
> I find my solution here cumbersome and complex, is there an easier way to breakdown this problem? (perhaps using lambda's)
> 
> 
> 

Try this using a stream approach. This also includes your request to use a Lambda.

```

Function<int[], Integer> findLucky = arr->IntStream.of(arr).boxed()
        .collect(Collectors.groupingBy(Function.identity(),
                Collectors.counting()))
        .entrySet()
        .stream()
        .filter(e -> e.getKey().equals(e.getValue().intValue()))
        .mapToInt(e->e.getKey().intValue())
        .max().orElseGet(()->-1);

```

And do the following to apply it

```

int v = findLucky.apply(new int[]{1, 2, 2, 3, 3, 3});
System.out.println(v);
v = findLucky.apply(new int[]{2, 2, 2, 3, 3});
System.out.println(v);
v = findLucky.apply(new int[]{5});
System.out.println(v);

```

Prints

```
3
-1
-1

```

* First it does a frequency count using the passed array
* Then it checks the Entries to find the largest when the key equals to value.
* It then returns if it exists or -1 if not.