Java Generics and Functions - java

I have a function
public static void printTreeMap (TreeMap <Object, ArrayList> map, PrintStream ps)
and a TreeMap:
TreeMap <Integer, ArrayList<MyClass>> tm = new TreeMap<>();
When I'm trying to call printTreeMap like that: printTreeMap(tm, System.out);, I get an exception
The method printTreeMap(TreeMap<Object,ArrayList>, PrintStream) in the type task_v7 is not applicable for the arguments (TreeMap<Integer,ArrayList<MyClass>>, PrintStream) Java(67108979)
How can I fix it?

I would suggest this approach. Note that for general methods of this type there is no a priori knowledge of those types. Therefore, this relies solely on the types involved overriding toString().
public static <T,U> void printTreeMap(TreeMap<T, ArrayList<U>> tm, PrintStream st) {
tm.forEach((k,v)-> {
st.println(k);
for (U e : v) {
st.println(" " + e);
}
});
}
Note that T and U need not be different as both could be the same type.
Here is an example.
TreeMap<Integer, ArrayList<MyClass>> tm = new TreeMap<>();
tm.put(10, new ArrayList<>(
List.of(new MyClass("Alpha"), new MyClass("Beta"))));
tm.put(30, new ArrayList<>(
List.of(new MyClass("Gamma"), new MyClass("Delta"))));
printTreeMap(tm, System.out);
Prints
10
Alpha
Beta
30
Gamma
Delta
The class
class MyClass {
String a;
public MyClass(String a) {
this.a = a;
}
public String toString() {
return a;
}
}
A more versatile approach for any Map of Lists would be the following:
public static <L extends List<?>, M extends Map<?,L>> void printMapOfLists(M tm,
PrintStream st) {
tm.forEach((k, v) -> {
st.println(k);
for (Object e : v) {
st.println(" " + e);
}
});
}

Related

Pass parameter to lambda expression - Java

My program requires that I accept a user input and, based on this input, a method is to be carried out. My basic thoughts are described well by the following question/answer:
How to call a method stored in a HashMap? (Java)
To do this, I have created an array of lambda expressions:
public final Runnable[] userCommandMethods = {
() -> userCommand1(),
() -> userCommand2(),
};
And an array of keys:
public final String[] userCommandKeys = {
commandKey1,
commandKey2,
};
Which are joined to create a HashMap using the following method:
public Map<String, Runnable> mapArrays (String[] array1, Runnable[] array2) {
Map<String, Runnable> mappedArrays = new HashMap<String, Runnable>();
for (int i = 0; i < array1.length; i ++) {
mappedArrays.put(array1[i], array2[i]);
}
return mappedArrays;
}
When I attempt to run a method by using myHashMap.get(userInput).run(); it works perfectly, provided none of the methods in userCommandMethods require input parameters.
My question:
How would I pass an input parameter (specifically a Hash Map) into the methods contained within userCommandMethods?
When the userCommand1() method takes an input parameter, but the lambda expression does not, I get the following error:
The method userCommand1(Map<String, String>) in the type ProgramCommands is not applicable for the arguments ()
However, when I do pass a parameter to the method, it states that it cannot be resolved to a variable.
Edit: to elaborate:
When the userCommand1() method takes no arguments:
public void userCommand1 () {
// Do some stuff
}
It works perfectly fine. However, I am unsure how to use the lambda expressions if the method does take an input parameter:
public void userCommand1 (Map<String, String> myMap) {
// Do some stuff
}
You just need to choose another functional interface (not Runnable).
For example, if your methods all take a String parameter, you should use Consumer<String>. If they take a String and an int, then you should use BiConsumer<String, Integer>. If your methods need more than 2 parameters, you need to create your own functional interface. For an example, see my answer here.
// use a list instead of an array, because arrays don't work well with generic types
public final List<Consumer<String>> userCommandMethods = List.of(
x -> userCommand1(x),
x -> userCommand2() // it's fine if the method takes fewer parameters
);
Instead of run, you would call accept, which is what Consumer and BiConsumer's single abstraction method is called.
Note that you can also use the method reference syntax. If userCommand1 is static, x -> userCommand1(x) can be rewritten as SomeClass::userCommand1 where SomeClass is the enclosing class of userCommand1. If userCommand1 is non static, it can be rewritten as this::userCommand1.
You don't need to build the map from two arrays. You can use ofEntries and entry to write the entries inline.
private final Map<String, Consumer<String>> someMap = Map.ofEntries(
Map.entry("foo", SomeClass::userCommand1),
Map.entry("bar", SomeClass::userCommand2),
Map.entry("baz", SomeClass::userCommand3),
// and so on
)
You are using Runnable interface that takes no argument on input:
#FunctionalInterface
public interface Runnable {
public abstract void run();
}
Instead, you can define your custom interface and consume it.
As a simple example:
#FunctionalInterface
public interface RunnableWithArg {
void apply(String t) throws RuntimeException;
}
And implementation may look like:
public class RunnableTest {
//also fine:
//public final RunnableWithArg[] userCommandMethods = { t -> this.userCommand1(t), t -> this.userCommand2(t) };
public final RunnableWithArg[] userCommandMethods = { this::userCommand1, this::userCommand2 };
public String commandKey1 = "commandKey1";
public String commandKey2 = "commandKey2";
public final String[] userCommandKeys = { commandKey1, commandKey2, };
public Map<String, RunnableWithArg> mapArrays(String[] array1, RunnableWithArg[] array2) {
Map<String, RunnableWithArg> mappedArrays = new HashMap<>();
for (int i = 0; i < array1.length; i++) {
mappedArrays.put(array1[i], array2[i]);
}
return mappedArrays;
}
public void userCommand1(String data) {
System.out.println("userCommand1 called with " + data);
}
public void userCommand2(String data) {
System.out.println("userCommand2 called with " + data);
}
public void test()
{
var fncMap = mapArrays(userCommandKeys, userCommandMethods);
for(String key: fncMap.keySet())
{
var fnc = fncMap.get(key);
fnc.apply(key);
}
}
}
And of course you can also define some generic types of "#FunctionalInterface" like this, so you can use it for both taking input and returning some output of generic types:
#FunctionalInterface
public interface AbcFunction<T, R> {
R apply(T t) throws AbcException;
static <T> Function<T, T> identity() {
return t -> t;
}
}
Is this something you are thinking of?
interface Command<T> {
public void run(T arg);
}
class SayHelloCommand implements Command<String>{
public void run(String name){
System.out.println("hello " + name);
}
}
class CountCommand implements Command<Integer>{
public void run(Integer limit){
for(int i=0; i<=limit; i++)
System.out.println(i);
}
}
public class Main{
public static void main(String[] args) {
Command[] commands = new Command[3];
commands[0] = new SayHelloCommand();
commands[1] = new CountCommand();
commands[0].run("Joe");
commands[1].run(5);
}
}

Anonymous class do not have an argument

I am learning Apache Spark. Given such an implementation of spark using java below, I am confused about some details about it.
public class JavaWordCount {
public static void main(String[] args) throws Exception {
if (args.length < 2) {
System.err.println("Usage: JavaWordCount <master> <file>");
System.exit(1);
}
JavaSparkContext ctx = new JavaSparkContext(args[0], "JavaWordCount",
System.getenv("SPARK_HOME"), System.getenv("SPARK_EXAMPLES_JAR"));
JavaRDD<String> lines = ctx.textFile(args[1], 1);
JavaRDD<String> words = lines.flatMap(new FlatMapFunction<String, String>() {
public Iterable<String> call(String s) {
return Arrays.asList(s.split(" "));
}
});
JavaPairRDD<String, Integer> ones = words.map(new PairFunction<String, String, Integer>() {
public Tuple2<String, Integer> call(String s) {
return new Tuple2<String, Integer>(s, 1);
}
});
JavaPairRDD<String, Integer> counts = ones.reduceByKey(new Function2<Integer, Integer, Integer>() {
public Integer call(Integer i1, Integer i2) {
return i1 + i2;
}
});
List<Tuple2<String, Integer>> output = counts.collect();
for (Tuple2 tuple : output) {
System.out.println(tuple._1 + ": " + tuple._2);
}
System.exit(0);
}
}
According to my comprehension, begin in line 12, it passed an anonymous class FlatMapFunction into the lines.flatMap() as an argument. Then what does the String s mean? It seems that it doesn't pass an created String s as an argument, then how will the FlatMapFunction<String,String>(){} class works since no specific arguments are passed into?
The anonymous class instance you're passing is overriding the call(String s) method. Whatever is receiving this anonymous class instance is something that wants to make use of that call() method during its execution: it will be (somehow) constructing strings and passing them (directly or indirectly) to the call() method of whatever you've passed in.
So the fact that you're not invoking the method you've defined isn't a worry: something else is doing so.
This is a common use case for anonymous inner classes. A method m() expects to be passed something that implements the Blah interface, and the Blah interface has a frobnicate(String s) method in it. So we call it with
m(new Blah() {
public void frobnicate(String s) {
//exciting code goes here to do something with s
}
});
and the m method will now be able to take this instance that implements Blah, and invoke frobnicate() on it.
Perhaps m looks like this:
public void m(Blah b) {
b.frobnicate("whatever");
}
Now the frobnicate() method that we wrote in our inner class is being invoked, and as it runs, the parameter s will be set to "whatever".
All your are doing here is passing a FlatMapFunction as argument to the flatMap method; your passed FlatMapFunction overrides call(String s):
JavaRDD<String> words = lines.flatMap(new FlatMapFunction<String, String>()
{
public Iterable<String> call(String s)
{
return Arrays.asList(s.split(" "));
}
});
The code implementing lines.flatMap could look like this for instance:
public JavaRDD<String> flatMap(FlatMapFunction<String, String> map)
{
String str = "some string";
Iterable<String> it = map.call(str);
// do stuff with 'it'
// return a JavaRDD<String>
}

Reflection with Enums

I have 4 almost same function and would like to refactor them in one. I thought to use reflexy, but I don't understand how to init EnumMap with reflexy.
code of functions like this:
private void loadRealEstateValues() {
realEstateValues = new EnumMap<RealEstateType, String>(RealEstateType.class);
for (RealEstateType r : RealEstateType.values()) {
realEstateValues.put(r, ResUtils.getStringByName(context,
String.format("%s_%s", getParserPrefix(), r.toString().toLowerCase())));
}
}
private void loadPeriodValues() {
periodValues = new EnumMap<PeriodType, String>(PeriodType.class);
for (PeriodType p : PeriodType.values()) {
periodValues.put(p, ResUtils.getStringByName(context,
String.format("%s_%s", getParserPrefix(), p.toString().toLowerCase())));
}
}
ways to put values I found like this, Maybe is a better?
Class<?> c= TestEnum.class;
testEnumMap = new EnumMap<TestEnum, String>(TestEnum.class);
for(Object m : c.getEnumConstants()){
testEnumMap.put((TestEnum) m, "bla bla blah");
}
Use a generic method:
private <T extends Enum<T>> EnumMap<T, String> loadEnumValues(Class<T> enumClass) {
EnumMap<T, String> map = new EnumMap<T, String>(enumClass);
for (T t : enumClass.getEnumConstants()) {
map.put(t, ResUtils.getStringByName(context,
String.format("%s_%s", getParserPrefix(), t.toString().toLowerCase())));
}
return map;
}

Code for building generic chains of validations and transformations to an object

I am trying to write some general code to do the following. Given two kinds of "operations", (a) validation (eg. input: object & context -> output: boolean), and (b) transformation (eg. input: object_A, context -> output: object_B) -objects of any type-.
I want to be able to build chains of "operations", in which an input object and its context can be submitted through (eg. to validate and transform the object). Returning immediately if the object is "invalid" and being able to get the transformed object if it finished "valid".
Idea is that "validations" and "transformations" can be "plugable" functions that other people write and assemble in a chain (eg. they build chains and submit objects through them).
I managed to do the following code, which compiles and seems to work. However, I'm not an expert on generics and would like to hear feedback about possible pitfalls, enhancements, or even maybe some other better/easier approach to the problem. Thanks in advance.
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
interface Operation<T, U, V> {
U execute(T a, V context);
}
abstract class Validation<T, V> implements Operation<T, Boolean, V> {
#Override
public Boolean execute(T a, V context) {
return executeValidation(a, context);
}
public abstract Boolean executeValidation(T a, V context);
}
abstract class Transformation<T, U, V> implements Operation<T, U, V> {
#Override
public U execute(T a, V context) {
return executeTransformation(a, context);
}
public abstract U executeTransformation(T a, V context);
}
class OperationsChain {
List<Operation<Object, Object, Object>> operations = new ArrayList<Operation<Object, Object, Object>>();
Object currentObj;
public <T, V> Boolean run(T a, V context) {
Boolean valid = false;
currentObj = a;
for (Operation<Object, Object, Object> operation : operations) {
if (operation instanceof Validation) {
valid = (Boolean) operation.execute(currentObj, context);
} else if (operation instanceof Transformation) {
currentObj = operation.execute(currentObj, context);
}
if (!valid) {
break;
}
}
return valid;
}
#SuppressWarnings("unchecked")
public <T, U, V> void addOperation(Operation<T, U, V> operation) {
operations.add((Operation<Object, Object, Object>) operation);
}
public Object getCurrentObject() {
return currentObj;
}
}
class ValidationOne extends Validation<MapObject, Map<String, Object>> {
public Boolean executeValidation(MapObject a, Map<String, Object> context) {
if (context.containsKey("validation 1")) {
return (Boolean) context.get("validation 1");
} else {
return false;
}
}
}
class ValidationTwo extends Validation<MapObject, Map<String, Object>> {
public Boolean executeValidation(MapObject a, Map<String, Object> context) {
if (context.containsKey("validation 2")) {
return (Boolean) context.get("validation 2");
} else {
return false;
}
}
}
class TransformationOne extends Transformation<MapObject, MapObject, Map<String, Object>> {
public MapObject executeTransformation(MapObject a, Map<String, Object> context) {
if (context.containsKey("transformation 1")) {
a.addField("data", (String) context.get("transformation 1"));
}
return a;
}
}
class MapObject {
Map<String, String> fields = new HashMap<String, String>();
public void addField(String key, String value) {
fields.put(key, value);
}
public String getField(String key, String value) {
if (fields.containsKey(key)) {
return fields.get(key);
} else {
return null;
}
}
public String toString() {
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry : fields.entrySet()) {
sb.append(entry.getKey());
sb.append(": ");
sb.append(entry.getValue());
sb.append("\n");
}
return sb.toString();
}
}
class OperationsChainDriver {
public static void main(String[] args) {
OperationsChain oc = new OperationsChain();
oc.addOperation(new ValidationOne());
oc.addOperation(new TransformationOne());
oc.addOperation(new ValidationTwo());
oc.addOperation(new TransformationOne());
Map<String, Object> context = new HashMap<String, Object>();
context.put("validation 1", true);
context.put("validation 2", false);
context.put("transformation 1", "aloha");
MapObject mapObject = new MapObject();
mapObject.addField("field 1", "hello");
Boolean result = oc.run(mapObject, context);
if (result == true) {
System.out.println("valid\n"+oc.getCurrentObject().toString());
} else {
System.out.println("invalid\n"+oc.getCurrentObject().toString());
}
}
}
Generics are about type safety - not having to cast, because as you surely know casts are risks proved runtime. You have a very generic design yet get very concrete to and the like and have to cast a lot - this shouldn't happen since it defeats the reason to use generics at all.
As as side note: why not give an operation a method isValid that has always a return type of Boolean, a transformation can fail, too, so yo don't have to make a difference between validation and transformation. Or let it put a value in a context - the operation could know its context and could use it without casts. An operation chain could know its context and could get the results without casts.
Anyway - as long as you code has casts you are still not finished with it.
This kind of task is one that I think a functional language would be ideal for, e.g. Scala (which runs on the JVM and is perfect for interoperating with Java code), or Haskell (which doesn't run on the JVM, but has some other advantages).
OK, I understand if you don't want to learn a new programming language. But one of the key advantages would be that your code should be shorter and easier to read and reason about.

Converting lists of one element type to a list of another type

I'm writing an adapter framework where I need to convert a list of objects from one class to another. I can iterate through the source list to do this as in
Java: Best way of converting List<Integer> to List<String>
However, I'm wondering if there is a way to do this on the fly when the target list is being iterated, so I don't have to iterate through the list twice.
Java 8 way:
List<String> original = ...;
List<Wrapper> converted = original.stream().map(Wrapper::new).collect(Collectors.toList());
assuming Wrapper class has a constructor accepting a String.
My answer to that question applies to your case:
import com.google.common.collect.Lists;
import com.google.common.base.Functions
List<Integer> integers = Arrays.asList(1, 2, 3, 4);
List<String> strings = Lists.transform(integers, Functions.toStringFunction());
The transformed list is a view on the original collection, so the transformation happens when the destination List is accessed.
As an alternative to the iterator pattern, you can use a abstract generic mapper class, and only override the transform method:
create a generic collection mapper for any data type
[optional] create a library of methods that transform between different data types (and override the method)
use that library
the implementation:
// Generic class to transform collections
public abstract class CollectionTransformer<E, F> {
abstract F transform(E e);
public List<F> transform(List<E> list) {
List<F> newList = new ArrayList<F>();
for (E e : list) {
newList.add(transform(e));
}
return newList;
}
}
// Method that transform Integer to String
// this override the transform method to specify the transformation
public static List<String> mapIntegerToStringCollection(List<Integer> list) {
CollectionTransformer transformer = new CollectionTransformer<Integer, String>() {
#Override
String transform(Integer e) {
return e.toString();
}
};
return transformer.transform(list);
}
// Example Usage
List<Integer> integers = Arrays.asList(1,2);
List<String> strings = mapIntegerToStringCollection(integers);
This would be useful is you have to use transformations every time, encapsulating the process.
So you can make a library of collection mappers very easy.
If you are trying to get a list of elements within a list then use the below code.Here the list of objects contains attribute name and below gets you list of names from that list
inputList.stream().map(p -> p.getName()).collect(Collectors.toList());
You can write a mapping iterator that decorates an existing iterator and applies a function on it. In this case, the function transforms the objects from one type to another "on-the-fly".
Something like this:
import java.util.*;
abstract class Transformer<T, U> implements Iterable<U>, Iterator<U> {
public abstract U apply(T object);
final Iterator<T> source;
Transformer(Iterable<T> source) { this.source = source.iterator(); }
#Override public boolean hasNext() { return source.hasNext(); }
#Override public U next() { return apply(source.next()); }
#Override public void remove() { source.remove(); }
public Iterator<U> iterator() { return this; }
}
public class TransformingIterator {
public static void main(String args[]) {
List<String> list = Arrays.asList("1", "2", "3");
Iterable<Integer> it = new Transformer<String, Integer>(list) {
#Override public Integer apply(String s) {
return Integer.parseInt(s);
}
};
for (int i : it) {
System.out.println(i);
}
}
}
Lambdaj allows to do that in a very simple and readable way. For example, supposing you have a list of Integer and you want to convert them in the corresponding String representation you could write something like that;
List<Integer> ints = asList(1, 2, 3, 4);
Iterator<String> stringIterator = convertIterator(ints, new Converter<Integer, String> {
public String convert(Integer i) { return Integer.toString(i); }
});
Lambdaj applies the conversion function only while you're iterating on the result.
There is also a more concise way to use the same feature. The next example works supposing that you have a list of persons with a name property and you want to convert that list in an iterator of person's names.
Iterator<String> namesIterator = convertIterator(persons, on(Person.class).getName());
Pretty easy. Isn't it?
This Could be a solutions --> by using map
List<Employee> employee = Arrays.asList(new Emp(1, 100), new Emp(2, 200), new Emp(3, 300));
List<Employee> employeS = employee.stream()
.map(emp -> new Emp(emp.getId(), emp.getSalary * 100))
.collect(Collectors.toList());
employeS .stream() .forEach(s -> System.out.println("Id :" + s.getId() + " Salary :" + s.getSalary()));
That question does not iterate through the list twice. It just iterates once and by far is the only known method.
Also you could use some transformer classes in commons-collections of google-collections but they all do the same thing under the hood :) the following being one way
CollectionUtils.collect(collectionOfIntegers, new org.apache.commons.collections.functors.StringValueTransformer());
Well, you could create your own iterator wrapper class to do this. But I doubt that you would save much by doing this.
Here's a simple example that wraps any iterator to a String iterator, using Object.toString() to do the mapping.
public MyIterator implements Iterator<String> {
private Iterator<? extends Object> it;
public MyIterator(Iterator<? extends Object> it) {
this.it = it;
}
public boolean hasNext() {
return it.hasNext();
}
public String next() {
return it.next().toString();
}
public void remove() {
it.remove();
}
}
I think you would either have to create a custom List (implementing the List interface) or a custom Iterator. For example:
ArrayList<String> targetList = new ArrayList<String>();
ConvertingIterator<String> iterator = new ConvertingIterator<String>(targetList);
// and here you would have to use a custom List implementation as a source List
// using the Iterator created above
But I doubt that this approach would save you much.
Here's an on-the-fly approach. (There must be something already like this in the jdk; I just can't find it.)
package com.gnahraf.util;
import java.util.AbstractList;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
/**
*
*/
public class Lists {
private Lists() { }
public static <U,V> List<V> transform(List<U> source, Function<U, V> mapper) {
return new ListView<U, V>(source, mapper);
}
protected static class ListView<U, V> extends AbstractList<V> {
private final List<U> source;
private final Function<U, V> mapper;
protected ListView(List<U> source, Function<U, V> mapper) {
this.source = Objects.requireNonNull(source, "source");
this.mapper = Objects.requireNonNull(mapper, "mapper");
}
#Override
public V get(int index) {
return mapper.apply(source.get(index));
}
#Override
public int size() {
return source.size();
}
}
}

Categories