Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Map storing lambdas as values

I want to learn possibilities within "newer" syntax and API of Java. By newer I mean 10+ (let's say 10-13). It is mostly around declaration of lambdas and storing different implementations conforming to same signature as values in the map. As recently I work mostly with Gosu I could come with this snippet:

var longInput = 10000000L

new LinkedHashMap<String, block(long) : long>( {
    "byte"  -> (\x -> x as byte as long),
    "short" -> (\x -> x as short as long),
    "int"   -> (\x -> x as int as long),
    "long"  -> (\x -> x as long as long)
}).eachKeyAndValue(\key, value ->
  print("${longInput} ${value(longInput) == longInput ? "can" : "cannot"} be converted to ${key}")
)

I could do it similarly in Java 10:

import java.util.*;

public class Test {
    public static void main(String[] args) {
        long longInput = 10000000L;

        var conversions = new LinkedHashMap<String, Conversion<Long>>();
        conversions.put("byte",  (x) -> (long) (byte)  x.longValue());
        conversions.put("short", (x) -> (long) (short) x.longValue());
        conversions.put("int",   (x) -> (long) (int)   x.longValue());
        conversions.put("long",  (x) -> (long) (long)  x.longValue());

        conversions.forEach((key, value) -> {
            System.out.printf("%d %s be converted to %s%n", longInput, value.convert(longInput) == longInput ? "can" : "cannot", key);      
        });
    }
}

interface Conversion<T> {
    T convert(T input);
}

My questions:

  1. Could it be done without having a named interface but in similar 'anonymous' function way like in Gosu?
  2. Anything else that could make this more concise in Java?

Update: This is just some play around code which aim was to do double casting of primitive long to smaller types and back. Inspired by https://www.hackerrank.com/challenges/java-datatypes/problem. So from my point of view this I wanted to stay.

Using answers my current Java 10 code would look like this:

public class Test { 
    public static void main(String[] args) {
        var longInput = 10000000L;

        new LinkedHashMap<String, UnaryOperator<Long>>() {{
            put("byte",  (x) -> (long) (byte)  x.longValue());
            put("short", (x) -> (long) (short) x.longValue());
            put("int",   (x) -> (long) (int)   x.longValue());
            put("long",  (x) -> (long) (long)  x.longValue());
        }}.forEach((key, value) -> {
            System.out.printf("%d %s be converted to %s%n", longInput, value.apply(longInput) == longInput ? "can" : "cannot", key);        
        });
    }
}

like image 863
Marek Pulka Avatar asked Sep 06 '25 03:09

Marek Pulka


1 Answers

Could it be done without having a named interface but in similar 'anonymous' function way like in Gosu?

Java already has a FunctionalInterface similar to that you have defined. You can make use of UnaryOperator<Long> values inn your Map.

Anything else that could make this more concise in Java?

This would in my opinion read better:

Map<String, UnaryOperator<Long>> conversions = new LinkedHashMap<>();
conversions.put("byte", a -> (long) a.byteValue());
conversions.put("short", a -> (long) a.shortValue());
conversions.put("int", a -> (long) a.intValue());
conversions.put("long", a -> a); // UnaryOperator.identity()
like image 179
Naman Avatar answered Sep 07 '25 15:09

Naman