Use a specific consumer type for each item with a Java 8 thread

I have a Java 8 number stream:

Stream<Number> numbers = ...; 

I would like to iterate over a thread and call a specific consumer depending on the type of each item. That is, for Integer elements that I would like to call Consumer<Integer> , for Long a Consumer<Long> , etc.

There is a forEach() method, but it expects Consumer<? super Number> Consumer<? super Number> , requiring that an implementation (usually a Lambda expression) be included in instanceof for the most accurate type.

As for the API, I'm basically looking for something like this:

 numbers.forEach( callbacks -> { callbacks.on( Integer.class, i -> { /* handle Integer */ } ); callbacks.on( Long.class, l -> { /* handle Long */ } ) } ); 

Is there any existing API that will allow me to register a specific consumer for a subtype of a thread element just like that?

+5
source share
2 answers

Are you sure you don't want to just start the stream twice? It will be more readable.

But if you want, you can define the consumer of type checking as follows:

 public static<T> Consumer<Object> acceptType(Class<T> clazz, Consumer<? super T> cons) { return t -> { if (clazz.isInstance(t)) { cons.accept(clazz.cast(t)); } }; } 

Then you can combine multiple users with andThen :

 Consumer<Object> combined = acceptType(Integer.class, i -> ...) .andThen(acceptType(Long.class, lng -> ...)) 

If you want to hide andThen , you can define

 static<T> Consumer<T> doAll(Consumer<T>... consumers) { return Arrays.stream(consumers) .reduce(Consumer::andThen) .orElse(t -> {}); } 

Then he becomes

 nums.forEach(doAll( acceptType(Integer.class, i -> ...), acceptType(Long.class, lng -> ..), ... )); 
+5
source

I don’t know about such built-in modules, so here is the option: Collect all the Consumer in Map that the type it consumes depends on and find the right consumer. I would recommend this solution if you work with a large number of types, and these types can change dynamically. The most efficient solution (for processor consumption) will probably be to use switch on item.getType() .

 public class Casts { public static void main(String[] args) { Stream<Number> stream = Arrays.stream(new Number[] { 3, 4L }); Map<Class<?>, Consumer<? super Number>> consumers = new HashMap<>(); putCastConsumer(consumers, Long.class, i -> System.out.println("Mapped long " + i)); putCastConsumer(consumers, Integer.class, i -> System.out.println("Mapped int " + i)); consumeByType(stream, consumers); } public static <U, T extends U> void putCastConsumer( final Map<Class<?>, Consumer<? super U>> map, final Class<T> clazz, final Consumer<T> consumer) { map.put(clazz, value -> consumer.accept(clazz.cast(value))); } public static <T> void consumeByType( final Stream<T> stream, final Map<Class<?>, Consumer<? super T>> consumers) { stream.forEach(item -> consumers.get(item.getClass()).accept(item)); } } 
+1
source

Source: https://habr.com/ru/post/1245629/


All Articles