Java 8 functional interfaces verses functions - java

Suppose I have an application that needs to apply several custom transformation on strings. The needs will grow by time. The following two approaches do exactly the same thing, but I am wondering which one is more beneficial in the long run. Are they the same? Or, does one offer more benefits than the other as the number of transforms increase and vary?
Suppose we have these:
public static final String PL = "(";
public static final String PR = ")";
public static final String Q1 = "'";
Here is each approach's setup and usage.
Approach 1:
#FunctionalInterface
public interface StringFunction {
String applyFunction(String s);
}
public class StrUtils {
public static String transform(String s, StringFunction f) {
return f.applyFunction(s);
}
public static String putInQ1(String s) {
return Q1.concat(s).concat(Q1);
}
public static String putInParens(String s) {
return PL.concat(s).concat(PR);
}
// and so on...
}
Which I would use like this:
System.out.println(StrUtils.transform("anSqlStr", StrUtils::putInQ1));
System.out.println(StrUtils.transform("sqlParams", StrUtils::putInParens));
Approach 2:
Here, I use straightforward Function:
Function<String, String> putInQ1 = n -> Q1.concat(n).concat(Q1);
Function<String, String> putInParens = n -> PL.concat(n).concat(PR);
// and so on...
Which I would use like this:
System.out.println(putInQ1.apply("anSqlStr");
System.out.println(putInParens.apply("sqlParams");

You sketched two ways of offering a certain functionality
The first one is to explicitly offer it as a method
public static String putInQ1(String s) {
return Q1.concat(s).concat(Q1);
}
which is supposed to be used via a method reference.
The second one is to offer it as a Function object:
Function<String, String> putInQ1 = n -> Q1.concat(n).concat(Q1);
(Here, you did not say where these instances should be located. I assume that you would also create a class that contained all these Function instances as (possibly public static final fields)
JBNizet mentioned a third option: You could use the methods directly, and not via method references. Indeed, the purpose of the transform function is not entirely clear. The only justification for this would be that you want to pass in arbitrary method references there, but these method references would just be Function objects - like in the second approach...
However, in a technical sense, the difference is not so large. Just to illustrate the point: Both approaches can trivially be converted into each other! The method can be implemented based on the function object
public static String putInQ1(String s) {
return putInQ1.apply(s);
}
And a function object can be created from the method reference:
Function<String, String> putInQ1 = StringUtils::putInQ1;
So the main question may be: How do you want to offer this functionality to the user of your library?
For this, consider the use case the you have an input string, and want to put it into ( parentheses ), and the result into ' single quotes ':
String doItWithMethodReferences(String input) {
String result = input;
result = StrUtils.transform(result, StrUtils::putInParens);
result = StrUtils.transform(result, StrUtils::putInQ1);
return result;
}
String doItWithFunctionObjects(String input) {
String result = input;
result = StringFunctions.putInParens.apply(result);
result = StringFunctions.putInQ1.apply(result)
return result;
}
String doItWithMethods(String input) {
String result = input;
result = StrUtils.putInParens(result);
result = StrUtils.putInQ1(result);
return result;
}
You can see that there is hardly a difference between the approaches that would qualify one of them as "better" or "worse" than the other in terms of readability, except for the obvious fact that the last one is simpler than the first one by avoiding the unnecessary transform calls.
Of course, each of these methods could be written "more compactly", in a single line. But depending on the number and the structure of the operations, this could severely reduce the readability, and in fact, this leads to another point: I could imagine that extensibility may something to consider. Imagine you wanted to create a single operation that placed a string into '( single quotes and parentheses )' at once.
With methods:
public static String putInPandQ1(String s) {
return putInQ1(putInParens(s));
}
With functions:
Function<String, String> putInPandQ1 = putInParens.andThen(putInQ1);
I think that the andThen function would be a nice feature that helps to compose more complex string manipulations.
(But taking that arbitrarily far, one has to ask whether you are not actually attempting to implement a template engine or a new domain-specific programming language...)
A short note: All this seems fairly unrelated to performance. Whether you do return s0 + s1; or return s0.concat(s1) will often not matter, and in the few cases where it does matter, you can change the implementation later - because, given the functionality that is sketched in the question, the decision about using + or concat or some StringBuilder trickery is exactly that: An implementation detail.
And another note, as pointed out in the comments: Instead of defining your own StringFunction interface, you could use UnaryOperator<String>. Both are "structurally equal", but the first one is part of the standard API. Imagine that there are already many libraries out there, with methods that expect the standard UnaryOperator<String> as an argument. When you only have instances of your own StringFunction, then you may have to convert these instances so that your code can cooperate with other code. This is trivial, of course, but the interfaces in the functional package are carefully chosen to cover a large range of application cases, and I think that the interoperability between libraries can be greatly increased when programmers don't needlessly create new interfaces that already exist in the standard API. One could argue that the introduction of the StringFunction makes code easier, because it does not need the <String> generic parameter. But if you want this, then you should simply declare the iterface as interface StringFunction extends UnaryOperator<String> { }, which simply is a further specialization, and will keep the compatibility with other code. Additionally, you'll then conveniently inherit all the default methods from Function, like the andThen that I mentined above.

Why not simply define the method 'putInWhatever(String s, String left, String right) {
return left + s + right;
}
with overloaded variants in case left and right are equal. No complicated functional interfaces and lambda's needed

Related

Why would one use a `java.util.function.supplier`, when one can just call a method?

I saw some example of of using supplier interface at https://dzone.com/articles/supplier-interface.
My question is, if in the above example I could do something as easy as :
driveVehicle(new Vehicle());
driveVehicle(new Car());
Why would one want to use supplier interface, if all it does is call a method, without taking in any parameters.
Suppose you have parameters stored in database that you want to keep in constant all over your app
// Assume retrieveSystemParameter query database which allows to change parameters
public static String SYSTEM_PARAMETER = StaticUtilities.retrieveSystemParameter();
That value will be initialized once and won't change untill a redeployment. That being said, if instead you use a supplier :
public static Supplier<String> SYSTEM_PARAMETER_SUPPLIER = StaticUtilities::retrieveSystemParameter;
When you need the value somewhere you will call SYSTEM_PARAMETER_SUPPLIER.get() which will retrieve parameter in the database when needed - that way if you change a parameter in database, you won't have to redeploy.
As you can see, Suppliers are lazy. They do the work when you ask them to work (by calling .get()) - that may allow you some performance gain if you deal with them wisely. Sometimes you will call a method which expect a variable X passing in method retrieveX and then end up not needing X in the method because some conditions were not met. In that case you will lose performance as you will execute the code to retrieve X while a supplier that retrieve X would only execute it when calling .get and you would only do that call if the conditions were met.
Disclaimer : the system parameter constant is just the first example that came to my mind, but considering it query the database on each .get() you'd rather cache the parameter and have the cache call .get() at a specific interval.
I guess Optional might be perfect example. Consider the following snippet:
final Product firstProduct = Optional.ofNullable(product)
.orElse(productDao.findProductById(id));
final Product secondProduct = Optional.ofNullable(product)
.orElseGet(() -> productDao.findProductById(id));
You're getting a product that may be null. In order to determine firstProduct java will have to call expression in orElse method so no matter product is null or not you always have to determine value that will be returned in case product is null.
In order to determine secondProduct database doesn't have to be queried in case product is not null because you're passing a Supplier that will be called only if product is null.
Another example is when your method that accepts a supplier is not pure (i.e., it has side effect), and the side effect happens before calling the lambda, and the behaviour of the lambda is affected by the side effect.
Consider, for instance, this example:
public class TestClass {
private String field;
public String getField() {
return field;
}
public void method(Supplier<String> supplier) {
field = "This is";
System.out.println(supplier.get() + " a test");
}
public static void main(String[] args) {
TestClass c = new TestClass();
c.method(() -> c.getField());
}
}
Here, method() is not pure, as it changes the value of field, which is used later in the lambda (through calling the getField() method). As the lambda is called in place (i.e., when get() is called), calling getField() will happen after setting the field. In other words, method() accepts a Supplier<String> instead of a String in an attempt to let the clients safely call the getField() method.
Of course, having side effects should be avoided wherever possible, and this is just a toy example, but it shows a potential place where a supplier can be used.
Supplier adds one more level of indirection.
Given that "All problems in computer science can be solved by another level of indirection", it's likely that there are some problems that can be solved by using a Supplier.
Beware, however, of the corollary "...except for the problem of too many layers of indirection."
So, if there's no problem to solve, then Supplier is overkill and you should stick to directly invoking new.
Put differently: mistrust any "pattern" or "best practice" that doesn't start by explaining a problem (your question shows, you actually do mistrust, so just keep on asking this kind of questions).
I use it to avoid the unnecessary creation of additional states:
private Supplier<Boolean> detach = () -> false;
private Supplier<Boolean> isAttached = () -> false;
private Supplier<Integer> index = () -> null;
private final Function<List<ObserverWrapper<X, Y>>, Boolean> attachFun = observers -> {
isAttached = () -> observers.contains(this);
detach = () -> observers.remove(this);
index = () -> observers.indexOf(this);
return observers.add(this);
};
public boolean attach(List<ObserverWrapper<X, Y>> observers) {
return attachFun.apply(observers);
}
public boolean isAttached() {
return isAttached.get();
}
public Integer observerIndex() {
return index.get();
}
Which some would say is unnecessary in itself, but then it becomes a philosophical problem.
A problem which would not exist if computers didn't exist, and then it becomes a real world problem of indirection.
I may admit that suppliers for me may have become an addiction, but in my mind they feel like the natural extrapolation and extension of all the programming axioms and principles.
You could use a Supplier in a map based factory class
public class StackService {
final static String INTEGERS = "Integers";
final static String DOUBLES = "Doubles";
final static String STRINGS = "Strings";
final static Map<String, Supplier<Stack>> stackType;
static {
stackType = new HashMap<>();
stackType.put(INTEGERS, Stack<Integer>::new);
stackType.put(DOUBLES, Stack<Double>::new);
stackType.put(STRINGS, Stack<String>::new);
}
public Stack<?> createStackOfType(String stackType) {
return stackType.get(stackType).get();
}
}
Here if you were to just use new Stack() you would be returning a reference to the same object rather than a new one.

Java: When to use attributes, when to use method parameters?

I tried googling and searching for this question but somehow couldn't find anything relevant about it. I'm wondering if there is a bbest-practise guide on when to use attributes in a class and when not, but rather use parameters to the single methods.
Many cases are clear to me, e.g.
public class Dog
{
private name;
public setName(...) {....}
}
But sometimes it's not clear to me what's better to use.
E.g. the following, either use:
public class calculation
XYZ bla;
public calculation(XYZ something)
{
this.bla = something;
}
public void calc1()
{
// some calculations with this.bla
}
public void calc1()
{
// some more calculations with this.bla
}
public XYZ getBla()
{
return this.bla;
}
}
or maybe do:
public class calculation
public calculation() {}
public static XYZ calc1(XYZ bla) // maybe static, if not dependant on other attributes/instance-variables etc
{
// some calculations with bla
return bla;
}
public static XYZ calc1() // maybe static, if not dependant on other attributes/instance-variables etc
{
// some more calculations with bla
return bla;
}
}
I mean you can argue for both cases. I see advantages and maybe disadvantages for both different styles, but somehow I prefer the second one as far as long as there are not too many arguments/parameters needed. Sure, if I need many many more attributes etc., then the first one will be better, simpler etc. because I dont need to pass so many parameters to the method...
Just a question of personal style?
Or how to decide for one approach?
Thanks
EDIT: A better example: I'm curently doing much image processing and the question would be wether to store the image internally in the state of the object or not. I'm currently NOT doing it because I'm using static methods, and psasing the image itself I to each method:
public class ImageProcessing
{
/**
*
*/
public static Mat cannyEdges(Mat I, int low, int high)
{
// ...
return I;
}
public static Mat cannyEdges(Mat I)
{
return ImageProcessing.cannyEdges(I, ContourDetection.CANNY_LOWTHRES, ContourDetection.CANNY_HIGHTHRES);
}
/**
*
*/
public static Mat getHoughLines(Mat Edges, ...some_conf_vars...)
{
// ...
return I;
}
}
and then I'm calling it from the outside like this e.g.:
// here: read image to I...
Mat edges = ImageProcessing.cannyEdges(I, 20, 100);
Mat lines = ImageProcessing.getHoughLines(I);
// draw lines...
question is: Does I belong to the state of the object? Would it make sense to convert to non-static and then use for example:
// here: read image to I...
ImageProcessing IP = new ImageProcessing(I);
IP.cannyEdges(20, 100); // CHANGE OF cannyEdges: Also save `edges` internally as property!?
IP.calcHoughLines(); // also save the lines internally maybe?
Mat lines = IP.getLines();
// draw lines...
is this nicer?
The question arising is then again: Should I for example store the result of getHoughLines() (i.e. the lines) internally or should I directly return it to the caller!?
I can use some examples:
public class Multiplier {
private int number;
public Multiplier(int number) {
this.number = number;
}
public int multiply(int other) {
return number * other;
}
}
This class could be instantiated like:
Multiplier multiplyByTwo = new Multiplier(2);
I could use it to multiply many elements on a list by 2.
But I could need to multiply pairs of numbers. So the following class could be what I neeed:
public class Multiplier {
public static int multiply(int number, int other) {
return number * other;
}
}
I could make it static since no state is needed.
This example could be used like this on a list:
for (int x:listOfInts) {
print(Multiplier.multiply(x * 2));
}
But probably in this specific case the 1st example was nicer.
for (int x:listOfInts) {
print(multiplyByTwo(x));
}
or even nicer used with a Java 8 ''map''
If I need to get the elements of the multiplication and the result at many points in my code i could do.
class Multiplier {
private int x;
private int y;
public int multiply() {
return x * y;
}
// getters and setters for x and y
}
In this last case I may consider not adding setters and pass x, y in the constructor.
Every structure could be used in some specific cases.
It's not entirely a question of personal style. But nevertheless, I assume that this topic might be slightly controversial (opinion-based) and thus not perfectly suited for a Q/A-site.
However, the obvious question is: Does an object of the respective class really carry a state? That is, is there any benefit in having the state represented by an instance? If the sole purpose of the instance is to be an accumulator of variables that are modified with a sequence of set... calls and a final call to an execute() method, then there is usually no real justification for such an instance - except for avoiding to have a static method with "many" parameters.
I think that the advantages of static methods outweigh most of the potential clumsiness of calling a method with "many" parameters. One of the most important ones is probably that the approach with static methods doesn't increase the state space. Every field is another dimension in the state space, and documenting state space properly can be hard. Static methods enforce a more "functional" programming style: They don't have any side-effects, and thus, are thread-safe (which is becoming increasingly important).
(Note: All this refers to static methods that are not related to any static state - that should be avoided anyhow. And of course, this refers to methods that are not involved in or aiming at anything related to polymorphism).
And after all, one can easily call any static method from anywhere - even from within an instance method, and pass in some fields as parameters. The opposite is not so easy: When you want to call a method that depends on many instance fields, it can be a hassle when you first have to create an object and set the fields appropriately (still not knowing whether it is in a valid state to call the method). I also see the default methods of Java 8 as a nice application case where static utility methods come in handy: The default method may easily delegate to the utility method, because no state is involved.
There are a few reasons I'd go with the first option, i.e. an object with state over static functions, particularly for complex calculations but also for simpler ones.
Objects work better for the command pattern.
Objects work better for the strategy pattern.
Static methods can turn unit tests into a nightmare.
Static is an anti-pattern in OOP because it breaks polymorphism, with the side-effect that related techniques will break with it, e.g. open/closed, mocking, proxies, etc.
That's my 2c at least.
The weird part of your first example is that those calcX methods don't say anything about idempotency, so it's unclear what this.bla is when it's being manipulated. For complex computations with optional settings, an alternative is to construct an immutable object using a builder pattern, and then offer calcX methods that return the result based on fixed object state and parameters. But the applicability of that really depends on the use case, so YMMV.
Update: With your new code, a more OOP approach would be to decorate Mat. Favouring delegation over inheritance, you'd get something like
public class MyMat
{
private Mat i;
public MyMat(Mat i) {
this.i = i;
}
public Mat getBackingMat() {
return this.i;
}
public MyMat cannyEdges(int low, int high)
{
// ...
return new MyMat(I); // lets you chain operations
}
public MyMat cannyEdges()
{
return new MyMat(ImageProcessing.cannyEdges(I, ContourDetection.CANNY_LOWTHRES, ContourDetection.CANNY_HIGHTHRES));
}
public MyMat getHoughLines(...some_conf_vars...)
{
// ...
}
}
MyMat myMat = new MyMat(I);
lines = myMat.cannyEdges(20, 100).calcHoughLines();
This is just a guess, cause I have no idea what those things mean. :)
When not to use static:
If the result that will be returned is dependent on other variables (state) that make up your "calculation" class then static cannot be used.
However, if you are simply doing calculations on a variable, as the example implies, static is probably the way to go as it requires less code (For example to perform calc1 and then calc2 on a variable by the first method you would have to do:
calculation calc = new calculation(x)
calc.calc1();
calc.calc2();
XYZ y = calc.getBla();
while with the second example you could do
static import ...calculation.*;
...
XYZ y = calc2(calc1(x));

How to create dynamic IF statements? reflection?

Is it possible with reflection to create a dynamic IF statement?
I have seen examples with BeanShell (like this: Dynamic if statement evaluation problem with string comparison) but i would like to know if it was possible to do it without BeanShell, and be pointed to some examples to adapt to my needs.
Basically i have a statement of the form: A operator B.
A and B can be numbers (Doubles or ints) or strings, but always A is the same type as B.
operator can be !=, ==, >=, >, <= ,<, and even others which behavior may be defined trough a class of their own, another reason why i will use reflection, since i can take that string and use reflection to invoke the appropriate method.
I want (must) to avoid branching "if" and "switch" because the variations are too many and will change constantly with user generated input.
You can create a factory that returns the correct operator for the given input.
public class OperatorFactory {
private static final Map<String, Operator<?>> OPERATORS = new HashMap<String, Operator<?>>();
static {
OPERATORS.put("<Number", new LessThanNumOperator());
OPERATORS.put("==Number", new EqualToNumOperator());
OPERATORS.put("<String", new LessThanStringOperator());
...
}
public static Operator<?> getOperator(String someUserSpecifiedOp, Class<?> paramType) {
String key = someUserSpecifiedOp;
if (Number.class.isAssignableFrom(paramType)) {
key += "Number";
} else if (String.class.isAssignableFrom(paramType)) {
key += "String";
}
return OPERATORS.get(key);
}
}
public interface Operator<T> {
public boolean execute(T lhs, T rhs);
}
public class LessThanNumOperator implements Operator<Number> {
public boolean execute(Number lhs, Number rhs) {
return lhs.doubleValue() < rhs.doubleValue();
}
}
And then use it:
OperatorFactory.getOperator(userDesignatedOperation, lhs.getClass()).execute(lhs, rhs);
Reflection won't help. Reflection gives you information about your code structure (classes, methods, attributes), but it doesn't allow you to change and update existing code.
Don't try to generate new code, try instead of adding a way for users to change the behaviour of your app depending on their input.
I don't know exactly what you are trying to do. Post some examples of user input and expected behaviour to help narrow the options down. But here is a few things that might help you in your task:
Have a user interface that helps your user select the time of the operands, with text fields for values, and a dropdown box for the operator. Simple solution, but I wouldn't recommend it as it may add complexity to the user interface.
Write a parser for your expressions. Writting a simple parser for this very simple language (A operator B) should be doable in reasonable time.
Domain Specific Languages. Allows the users of your application to write some scripts that get interpreted by your application and respond in some way. You could imagine a DSL consisting in simple comparisons, and the results will influence the behaviour of your app. Have a look at Groovy, it is a good language for this use case.
You could make a interface like this
public interface MyComparator
{
public boolean matches(String operator);
public boolean compare(String a, String b);
}
Then you could make how many classes you want all implementing the interface like this
public class MyEquals implements MyComparator
{
#Override
public boolean matches(String operator)
{
return "==".equals(operator);
}
#Override
public boolean compare(String a, String b)
{
return a.equals(b);
}
}
and load them like this:
Class compClass = Class.forName(classname);
MyComparator comp = (MyComparator)compClass.newInstance();
you could so prepare a list of all available operators and iterate over it and even have the list of operators configured on a properties file.

What is the use of Method Overloading in Java when it is achieved by changing the sequence of parameters in the argument list? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I was reading a Java training manual and it said that Method Overloading in Java can be achieved by having a different argument list. It also said that the argument list could differ in
(i). Number of parameters
(ii). Datatype of parameters
(iii). Sequence of parameters
My concern is about (iii).
What is the use of trying to overload a method just by changing the sequence of parameters? I am unable to think of any benefits by this way.
(iii) is just a special case of (ii).
"int, long, String" and "String, int, long" are (ii) = different datatypes, but just happen to be the same set of types.
But yeah, promiscuous overloading leads to confusing code.
Method overloading is useless if your intent is solely parameter sequence, because IMHO, you're just encouraging boilerplate code (repeating identical code), and if the parameters are all of the same data type, you'll receive a compilation error because the method signatures are ambiguous.
I do a lot of method overloading in APIs for convenience purposes when a parameter can exist as multiple data types:
public class Client {
public Status get(String request) {
return get(new Request(request));
}
public Status get(Request request) {
// do stuff
}
}
If you have a lot of parameters, and many of them are optional, I would suggest looking into the Builder pattern. The intent of the builder pattern is to create an immutable object constructed of optional parameters. For instance:
public String get(String arg0, String arg1, String arg2) {
// do stuff
}
public String get(String arg0, String arg1) {
return method(arg0, arg1, null);
}
public String method(String arg0) {
return method(arg0, null, null);
}
can probably be improved with a builder:
class Request {
final String arg0;
final String arg1;
final String arg2;
private Request(Builder b) {
this.arg0 = b.arg0;
this.arg1 = b.arg1;
this.arg2 = b.arg2;
}
// getter methods
public static class Builder {
String arg0, arg1, arg2;
public Builder arg0(String arg) {
this.arg0 = arg;
return this;
}
public Builder arg1(String arg) {
this.arg1 = arg;
return this;
}
public Builder arg2(String arg) {
this.arg2 = arg;
return this;
}
public Request build() {
return new Request(this);
}
}
}
class Client {
public String get(Request request) { }
}
new Client().get(Request.Builder().arg0("arg0").arg1("arg1").arg2("arg2").build());
Another overload that I do a lot is when a method can accept parameters of varying data types:
public String lookup(String variant) {
return lookup(Integer.parseInt(variant));
}
public String lookup(int ordinal) {
// logic
}
Ah! Makes sense! I was thinking in the lines of -
public String buildUrl(String protocol, String host, int port){
return protocol + "://" + host + ":" + port;
}
public String buildUrl(String protocol, int port, String host){
return protocol + "://" + host + ":" + port;
}
So, I was thinking that this was useless. But there might be a case like this (took a long time to come up with it :-)) -
public int countTotalTruckWheels(boolean hasSpare, int numberOfTrucks){
if(hasSpare){
return (numberOfTrucks+1)*4;
} else{
return numberOfTrucks*4;
}
}
public int countTotalTruckWheels(int numberOfAxlesInTruck, boolean strongAxle){
if(strongAxle){
//each axle can hold 4 wheels
return numberOfAxlesInTruck*4;
} else {
return numberOfAxlesInTruck*2;
}
}
Here the datatypes of the parameters are not just re-ordered, but the entire meaning of the parameters has been changed.
I understood this based on many answers above. I am unable to choose one particular answer. Also, I wanted to add this as a comment, but it was too big to be a comment. Hence added it here.
It also said that the argument list could differ in
(iii). Sequence of parameters
(iii) is simply wrong. You can't change overload by simply changing the order of the parameters. Take this example:
int add(int x, int y)
int add(int y, int x)
This is not a legal overloading. Now consider this example:
int fill(int number, char c)
int fill(char c, int number)
Remember the parameter names don't matter, so really, it looks like this to the compiler:
int pad(int, char)
int pad(char, int)
This is valid overloading, but not because you changed the order of the parameters, but rather because the types of one or more of the parameters changed. The two methods differ because the type of the 1st parameter is different between the methods (as is the type of the 2nd parameter).
What is the use of trying to overload a method just by changing the sequence of parameters?
There is no use. The text is NOT saying you "SHOULD" do method overloading by changing the sequence of parameters, the text is only saying that its possible (as long as the reordering creates a unique parameter signature). This is simply a consequence (a side-effect) of how overloading works - I feel certain in saying that it is not an use case that the language designers were trying to support. Put another way:
Just because you can do it, doesn't mean you should.
There are not many reasons to do that sort of overloading, but I can think of a couple.
Your API goes public, and all your method signatures but one for a fairly common (but uninherited) method are the same. Say they're all myFunct(String,int) and one of them happens to be myFunct(int,String) by accident. You will want to keep that function for backwards compatibility, but you'll also probably make that one class also have myFunct(String,int) to keep it consistent.
Another reason (even if it is a poor one) is that you may have people used to them in one order, perhaps from a different library, or maybe they're just dyslexic... but you might overload it to swap parameters if it's convenient to do so. Obviously, this can be tricky, because if you have (String,int,int) You probably don't want to do (int,int,String) or (int,String,int) ALSO. Best to keep it to just one.
You are right, iii does not make a strong cases usually. Typically, it is necessary to keep things strongly typed as show below
void save(String key, int value);
void save(String key, float value);
void save(String key, byte value);
etc.
It may seem somewhat pointless and in a lot of cases I can see why some people may simply shuffle parameter sequences around simply to support overloading where really they just have poorly designed code. However, it in some circumstances it make perfect sense.
Most programmers will choose certain parameter sequences based on a notion that such parameters make more sense in a particular order or because order is in-fact fundamentally important to the outcome of some calculation. Take these overloaded methods as an example:
int raise(int i, String n);
int raise(String i, int n);
As you learned very early on in math class, raising one value by another is a non-commutative operation (i.e. 2^3 != 3^2).
So in this example, each method will raise some numeric value by another. The first parameter is always the value that is intended to be raised by the value given as second parameter (order is important). However, as you can see, each argument to the parameter list may be represented by a String or an int type. The semantics of the operation however remains the same.
raise("12", 2);
raise(12, "2");
Of course this is a very contrived example for obvious reasons, but you can see how in principle it is reasonable.
I'm sure if i gave it a bit more though I could come up with a better example where the parameters are of some special type where this sort of thing makes even more sense.
Parameter lists are determined by the number and types of the parameters. So if your parameters have different types, re-ordering the parameters gives a different overload because the compiler sees different types in different slots.
f(int a, String b)
f(String b, int a)
Both functions have two parameters but the types don't match so they are valid overloads.
As to why you might want to do this, it is often the case that the order of the parameters matters. In the codebase I maintain we have Exceptions that potentially have a cause, a message, and other parameters. So the following two calls are not the same:
Exception cause;
String msgFormat = "An error occurred while processing {0}";
String recordName = "abc123";
throw new ABCException(cause, message, recordName);
throw new ABCException(message, cause, recordName);
throw new ABCException(message, recordName);
throw new ABCException(recordName, message);
In the first case cause is the cause of the exception, message is the message to display, and record is the parameter for the message. In the second case both cause and recordName are interpreted as parameters for the message. In the third case there is no cause and in the fourth case there is no cause and furthermore the message argument is in the wrong position and won't be processed properly.
This is accomplished by having several useful overloads of the ABCException constructor (though in this case we are using varargs to support unlimited numbers of parameters).

How can I map a String to a function in Java?

Currently, I have a bunch of Java classes that implement a Processor interface, meaning they all have a processRequest(String key) method. The idea is that each class has a few (say, <10) member Strings, and each of those maps to a method in that class via the processRequest method, like so:
class FooProcessor implements Processor
{
String key1 = "abc";
String key2 = "def";
String key3 = "ghi";
// and so on...
String processRequest(String key)
{
String toReturn = null;
if (key1.equals(key)) toReturn = method1();
else if (key2.equals(key)) toReturn = method2();
else if (key3.equals(key)) toReturn = method3();
// and so on...
return toReturn;
}
String method1() { // do stuff }
String method2() { // do other stuff }
String method3() { // do other other stuff }
// and so on...
}
You get the idea.
This was working fine for me, but now I need a runtime-accessible mapping from key to function; not every function actually returns a String (some return void) and I need to dynamically access the return type (using reflection) of each function in each class that there's a key for. I already have a manager that knows about all the keys, but not the mapping from key to function.
My first instinct was to replace this mapping using if-else statements with a Map<String, Function>, like I could do in Javascript. But, Java doesn't support first-class functions so I'm out of luck there. I could probably dig up a third-party library that lets me work with first-class functions, but I haven't seen any yet, and I doubt that I need an entire new library.
I also thought of putting these String keys into an array and using reflection to invoke the methods by name, but I see two downsides to this method:
My keys would have to be named the same as the method - or be named in a particular, consistent way so that it's easy to map them to the method name.
This seems WAY slower than the if-else statements I have right now. Efficiency is something of a concern because these methods will tend to get called pretty frequently, and I want to minimize unnecessary overhead.
TL; DR: I'm looking for a clean, minimal-overhead way to map a String to some sort of a Function object that I can invoke and call (something like) getReturnType() on. I don't especially mind using a 3rd-party library if it really fits my needs. I also don't mind using reflection, though I would strongly prefer to avoid using reflection every single time I do a method lookup - maybe using some caching strategy that combines the Map with reflection.
Thoughts on a good way to get what I want? Cheers!
There aren't any first-class standalone functions, but you can do what you want with an interface. Create an interface that represents your function. For example, you might have the following:
public interface ComputeString
{
public String invoke();
}
Then you can create a Map<String,ComputeString> object like you want in the first place. Using a map will be much faster than reflection and will also give more type-safety, so I would advise the above.
While you can't have first class functions, there are anonymous classes which can be based on an interface:
interface ProcessingMethod {
String method();
}
Map<String, ProcessingMethod> methodMap = new HashMap<String, ProcessingMethod>();
methodMap.put("abc", new ProcessingMethod() {
String method() { return "xyz" }
});
methodMap.put("def", new ProcessingMethod() {
String method() { return "uvw" }
});
methodMap.get("abc").method();
Or you could use Scala :-)
Couldn't you do String to Method? Then you can cache the methods you need to execute.
This example uses an enum of named functions and an abstract FunctionAdapter to invoke functions with a variable number of homogeneous parameters without reflection. The lookup() function simply uses Enum.valueOf, but a Map might be worth it for a large number of functions.
As you've noticed, you can do what you want using the Reflection API, but you loose some benefits of the Java compiler, on top of the issues you've already come up with. Would wrapping your Strings in an object and using the Visitor pattern solve your issue? Each StringWrapper would only accept a Visitor that has the right method, or something along those lines.
Use a Map where the key is a string and the value is an object that implements an interface containing method(). That way you can get the object containing the method you want out of the map. Then just call that method on the object. For example:
class FooProcessor implements Processor{
Map<String, FooMethod> myMap;
String processRequest(String key){
FooMethod aMethod = myMap.getValue(key);
return aMethod.method();
}
}
What about Method class from the reflection API? You can find methods of a class based on name, parameters, or return type. Then you just call Method.invoke(this, parameters).
That's pretty much the same as a Map from JavaScript you are talking about.
public class CarDetailsService {
private final CarRepository carRepository;
private final Map<String, Function<CarDTO, String>> carColumnMapper = new HashMap<>();
public ApplicationDetailsServiceImpl(CarRepository carRepository) {
this.carRepository = carRepository;
//---- Initialise all the mappings ------- //
carColumnMapper.put("BRAND", CarDTO::getBrandName);
carColumnMapper.put("MILEAGE", CarDTO::getMileage);
}
public Map<String, List<CarDTO>> getListOfCars(String groupBy) {
return carRepository.findAll()
.stream()
.map(toCarDTO)
.collect(groupingBy(carColumnMapper.get(groupBy.toUpperCase())));
}
Function<CarDetails, CarDTO> toCarDTO = (carDetails) -> CarDTO
.builder()
.brand(carDetails.getBrand())
.engineCapacity(carDetails.getEngineCapacity())
.mileage(carDetails.getMileage())
.fuel(carDetails.getFuel())
.price(carDetails.getPrice())
.build();
}

Categories