Memoization of a function of various inputs in Java - java

I have a costly function taking various double variables as inputs:
public double f(double v1, double v2, double v3){
...
return output;
}
So I tried to memoise its output, using two different strategies.
Nested HashMaps:
Map<Double,Map<Double,Map<Double,Double>>> map = new HashMap<>();
public double f(double v1, double v2, double v3){
// This is abbreviated: in my case I made sure to call only once each "get()"
if(map.containsKey(v1) && map.get(v1).containsKey(v2) && map.get(v1).get(v2).containsKey(v3))
return map.get(v1).get(v2).get(v3);
...
// calculations
...
// put "output" in the map (and create new intermediate HashMaps when needed)
...
return output;
}
Custom HashMap key:
public class DoubleKey {
public final double[] values;
public DoubleKey(double[] values){ this.values = values;}
#Override
public boolean equals(Object key){
if(key instanceof DoubleKey)
return Arrays.equals(values, ((DoubleKey)key).values);
return false;
}
#Override
public int hashcode(){
return Arrays.hashcode(values);
}
}
Map<DoubleKey,Double> map = new HashMap<>();
public double f(double v1, double v2, double v3){
DoubleKey key = new DoubleKey(new double[]{v1,v2,v3});
if(map.containsKey(key))
return map.get(key);
...
// calculations
...
map.put(key, output);
return output;
}
Now, I expected the second approach to be faster, as it uses a single Hashmap, and feels generally more elegant. But it turns out that I gain less benefit from the second method, compared to the first method which yields a great speed boost.
Do you know why would the second method be less efficient? Is it the cost of using Arrays.equals() and/or Arrays.hashcode()?
More generally, do you know of other memoization techniques that would be more efficient?

The two solutions are not equal. the first one hard coded support only 3 double args while the second one supports any number of args.
if you need to support only exactly 3 args, I think it is more efficient to hold 3 instance variables:
EDIT: following comments, replaced original answer that used varargs ctor with explicit individual args. probably more efficient (does not construct aray). also made instance vars final to enable compiler optimization
public class DoubleKey
{
final double arg1, arg2, arg3;
final int hashCode;
public DoubleKey(double arg1, double arg2, double arg3)
{
this.arg1 = arg1;
this.arg2 = arg2;
this.arg3 = arg3;
hashCode = Objects.hash(arg1, arg2, arg3);
}
#Override
public boolean equals(Object key)
{
if (key instanceof DoubleKey) {
DoubleKey dk = (DoubleKey) key;
return arg1 == dk.arg1 && arg2 == dk.arg2 && arg3 == dk.arg3;
}
return false;
}
#Override
public int hashCode()
{
return hashCode;
}
}
constructing DoubleKey instance is now preatier
DoubleKey key = new DoubleKey(v1,v2,v3);

Related

Provide arguments with a method

Is there a way in Java to create a method that would return the list of parameters of another method such that I am able to call
anotherMethod(method())
where anotherMethod has arbitrary arguments like
public void anotherMethod(int a, int b, String c)
And what is if the types stay the same, like with
public int add(int a, int b, int c)
If there is no such way, how could I model the list of parameters such that it would work? Is it a List or an array or something else?
If the number of parameters is fixed at the call site, you could use varargs
int add(int... numbers)
otherwise you'd use an array or collection
int add(int[] numbers)
You can then of course have another method provide the value of these parameters:
add(someOtherMethod())
Varargs
Java has a built-in feature to denote a variable length of arguments. It is called varargs (documentation) (variable arguments) and it only works if the type stays the same. The syntax for a method is like this:
public int add(int... values)
Note the int... values which denotes varargs. A caller can now call the method like
add(null) // Passing null
add(values) // Passing an int[]
add() // No arguments
add(a) // One int
add(a, b) // Two ints
add(a, b, c) // Three ints
add(a, b, c, d) // Four ints
...
Note the three special cases null, int[] and empty.
What Java does is it will convert the arguments into an array. So inside the method values will be a regular int[]. You could thus implement the method like
public int add(int... values) {
int sum = 0;
for (int value : values) {
sum += value;
}
return sum;
}
If you, as a caller, want to pass the return value of a function you just need to make sure that it returns an array like int[]. So the following would work:
public int[] valueProvider() {
int[] values = ...
return values;
}
and then call it like
int sum = add(valueProvider());
Collection, Iterable and Stream
Besides that, if you don't want to use varargs or arrays, you can use Collections (documentation). A collection may be a List or a Set and so on. For example you could declare
public int add(Collection<Integer> values)
and feed it like
Collection<Integer> values = new ArrayList<>();
values.add(1);
values.add(2);
int sum = add(values);
An Iterable<Integer>, in contrast to Collection<Integer> would even be more flexible.
Using a Stream (documentation) would also work like a charm and is probably one of the most flexible variants since the source of a stream could be anything and nearly anything of the standard library supports a stream representation.
Changing type
Now note that what you searched for in the beginning, a method that is able to feed arbitrary arguments, is not possible in Java.
The main problem is that the types may change, so you may have a method like
public void doSomething(int first, String second, File third)
and you won't be able to feed the method with varargs, Collections or any of the presented methods.
In that case you will need a wrapper class like
public class DoSomethingArguments {
private int mFirst;
private String mSecond;
private File mThird;
public DoSomethingArguments(int first; String second, File third) {
this.mFirst = first;
this.mSecond = second;
this.mThird = third;
}
// Some getters
}
(or a generic tuple class, a triple in this case)
But then you would need to change the method to
public void doSomething(DoSomethingArguments arguments)
what is probably not what you wanted since you probably intended to not change the signature of doSomething.
But unfortunately there is no way to feed a method like this in such a way.
There is nothing that works the way you wish for at compile time. As the other answers are pointing out, there are varargs. But that is just syntactical sugar. That is just the compiler implicitly creating an array of a certain type for you.
But beyond that, there is reflection. Reflection allows you to dynamically inspect classes and methods at *runtime.
In other words: you can do something like
Object whatever = ...
Class<?> someClass = whatever.getClass();
And now you can ask someClass about the methods it has. And which parameters they need.
But as said: all of that is runtime only. And it the reflection APIs are very easy to get wrong. And you only find out at runtime, when some exception is thrown.
There is not direct way to pass multiple values in the way you want. But you can use a indirect way to pass a group of values of different type. I can think of two ways but their can be more.
Firs - Use a map, just insert the values you want to pass in the collection and pass the collection to the second method.
Second - Create a bean (Java POJO) to pass as parameter to the consuming method.
A small sample code.
class Sample{
private int a;
private String b;
private int c;
Sample(int a,String b,int c){
this.a = a;
this.b = b;
this.c = c;
}
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
public int getC() {
return c;
}
public void setC(int c) {
this.c = c;
}
}
public class PassingExample {
public void consumerofInputs (Map<Integer, Object> input)/*(int a, String b, int c)*/{
System.out.println("I use three different inputs : int, string and int");
for (Map.Entry<Integer, Object> entry : input.entrySet()) {
System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue());
}
}
public Map producingInput() {
Map<Integer, Object> input = new HashMap<Integer, Object>();
input.put(1, 10);
input.put(2, "input");
input.put(3, 89);
return input;
}
public Sample createClassAsInput(){
Sample input = new Sample(10,"class-input",30);
return input;
}
public void useSampleAsInput(Sample input){
System.out.println("\nUsing Class as input \nInt::"+input.getA()+"\nString::"+input.getB()+"\nInt::"+input.getC());
}
public static void main(String[] args) {
PassingExample example = new PassingExample();
example.consumerofInputs(example.producingInput());
example.useSampleAsInput(example.createClassAsInput());
}
}

Java How to chain with Math class

I am at the very basics of learning Java, I have tried searching for this answer but maybe I do not know what I am searching for.
I want to perform multiple operations on a number, so far the only way I know how to do that is the have intermediate variables with operations performed one at a time. This can't be the best way. The following is code in my main method that I would love to have work:
double sqrtAbsInput = promptForDouble("I can get the square root of the absolute value.");
double sqrtAbsOutput = sqrtAbsInput.Math.abs().sqrt();
System.out.println(sqrAbsOutput);
promptForDouble() method returns a double, it is the second line that concerns me most. The error I get is
"error: double cannot be dereferenced."
I assume what's going on is the variable needs to be the argument of the Math class methods, but I understand it could also have to do with the variable being a primitive type.
abs and sqrt aren't methods of double (which is a primitive, so it doesn't have any methods anyway - as noted in the error message you're getting), but static method of Math that take a double as an argument and return a double result:
double sqrtAbsOutput = Math.sqrt(Math.abs(sqrtAbsInput));
Math class does not implement "builder pattern" (for efficiency reasons), but you can create your own Math class implementation which allows chaining.
Here is an example:
public class MathBuilder {
private double value;
public MathBuilder(double value) {
this.value = value;
}
public MathBuilder abs() {
value = Math.abs(value);
return this;
}
public MathBuilder sqrt() {
value = Math.sqrt(value);
return this;
}
// other builder-math methods...
public double build() {
return value;
}
}
Usage:
double result = new MathBuilder(-10).abs().sqrt().build();
Or with Java 8:
public class MathBuilder {
private double value;
public MathBuilder(double value) {
this.value = value;
}
public MathBuilder apply(DoubleUnaryOperator o) {
value = o.applyAsDouble(value);
return this;
}
public double build() {
return value;
}
}
Usage:
double result = new MathBuilder(-10)
.apply(Math::abs)
.apply(Math::sqrt)
.build();
You will have to do this:
System.out.println(Math.sqrt(Math.abs(sqrtAbsInput)));

Java: Why would someone widen and shorten a variable?

I'm taking a java course on lynda.com, and the course was explaining how to "cast" a variable if you want to shorten it.
WIDENING: Widening a variable is making it larger (e.g. int int1 = 4030; long long1 = int1;)
SHORTENING: Shortening a variable is making it smaller, and requires special syntax. (e.g. int int2 = 5024; short int3 = (short) int2;).
So, my question is, why would anyone want to do this? What's the advantage? If you know you'll need to widen a variable at some point, why don't you just start it as that variable? And why would you want to make your data type smaller if you're shortening? If you think that it could be used like this:
byte byte1 = 127;
byte1++;
if (byte1 > 127) {
short short1 = byte1;
}
(I know that this would give an error message, but you get the rough idea.)
You could do this, but why? It wouldn't save data, because it just adds more lines of code which would take up that data.
There are several reasons you might want to "shorten" a variable.
One is that an API or library you are working with requires data to be passed that is of a "shorter" type than the type you were using in your code.
Another is to save space. For example, if I only need to store a two digit number, using a long would be overkill as it would use much more system memory than is needed. This isn't something you normally need to worry too much about, but it could be an issue on certain systems or for very large projects.
There may be even more reasons; these are just a few examples.
You absolutely can't avoid this if you must pass a value received from a function that is out of your control into another function that is also out of your control:
package abc.def:
public class Foo {
public static long foo() { ... }
}
package xyz.qwerty:
public class Bar {
public static void bar(int n) { ... }
}
Your code:
import xyz.qwerty.Bar;
import abc.def.Foo;
...
Bar.bar((int)Foo.foo());
There may be intermediate variables temporarily holding the value received from Foo.foo() before it gets to Bar.bar() but that doesn't eliminate the inevitable need for converting from one type to another, which must happen somewhere in between.
Imagine you want to implement a min(...) method to calculate the minimum of two numbers. You could simply write:
public static double min(double lhs, double rhs) {
if (lhs >= rhs) {
return (lhs);
}
// else if (rhs > lhs) {
return (rhs);
// }
and through auto-casting (or what you refer to as "widening"), you could call this method with all primitives in Java. The downside, however, is that the result would always be double and if you want to save it as an int, you would have to downcast the result:
int i1 = 0;
int i2 = 100;
int max = (int) max(i1, i2);
It would be nice if the method returned an int iff. both parameters are int, a long iff. one parapeter is long and the other parameter is long or int and so on. This would result in the following code1:
public static int min(int lhs, int rhs) {
if (lhs >= rhs) {
return (lhs);
}
// else if (rhs > lhs) {
return (rhs);
// }
}
public static long min(long lhs, long rhs) {
if (lhs >= rhs) {
return (lhs);
}
// else if (rhs > lhs) {
return (rhs);
// }
}
public static float min(float lhs, float rhs) {
if (lhs >= rhs) {
return (lhs);
}
// else if (rhs > lhs) {
return (rhs);
// }
public static double min(double lhs, double rhs) {
if (lhs >= rhs) {
return (lhs);
}
// else if (rhs > lhs) {
return (rhs);
// }
}
Then you could write:
int i = 0;
long g = 1L;
float f = 2f;
double d = 3.0;
int intMax = max(i, i);
long longMax = max(i, g);
float floatMax = max(i, f);
double doubleMax = max(l, d);
Through the means of autocasting and method overloading, the most specific method will be called2,3.
1 You culd write those methods for byte, short and charas well. I would not recommend doing so since all arithemtic operations in Java return at least something of type int (e.g. byte + byte will return an int). This is due to the fact that the JVM does not know of the primitives boolean, char, byte and short, they are represented as int (see JLS §2.11.1).
2 The exact behaviour is specified in JLS, §15.12.2.5
3 This is actually the same mechanism used forjava.lang.Math's implementation of min(...), its implementation is slightly different.

Java type that holds two primitives of any primitive type

I want to store two primitive values (and I'm including String as a primitive here) inside a field. For example, I may want to store a String and an int as below:
("hello", 42)
So if the type I'm looking for is X, I'd like to be able to declare a field
private X myX = new X("hello", 42);
or some other incantation that gives me the same result.
I'm trying to figure out what type that field has to be. It has to accept any Java primitive type and String so it could be a String + int or String + float... actually any combination of primitive (+ String) types. Essentially, to borrow a concept from functional languages, I just want a tuple that's restricted to primitives. But Java doesn't have that.
Since they are primitives, generics don't work very well. And I'm not sure how I feel about boxing/unboxing.
What is the best data type/structure I can use in Java to do it?
Don't think that there is a way to do it with built-in Java libraries. However one could write Tuple class identical to Tuple2 class in Scala language like this:
public class Tuple<K, V> {
private K first;
private V second;
// create tuple only with static method "of"
private Tuple(K first, V second) {
this.first = first;
this.second = second;
}
public static <K, V> Tuple<K, V> of(K a, V b) {
return new Tuple<K, V>(a, b);
}
public Tuple<V, K> swap() {
return new Tuple<V, K>(second, first);
}
public K getFirst() {
return this.first;
}
public V getSecond() {
return this.second;
}
#Override
public String toString() {
return "(" + first.toString() + "," + second.toString() + ")";
}
public static void main(String[] args) {
Tuple myTuple = Tuple.of("hello", 2);
System.out.println("toString: "+myTuple);
System.out.println("First: "+myTuple.getFirst());
System.out.println("Swap: "+ myTuple.swap());
}
}
Output:
toString: (hello,2)
First: hello
Swap: (2,hello)
If you really want to store the values as one primitive type, you have to 'encode' them.
For example:
String field = "hello;42";
String[] values = field.split(";");
int intValue = Integer.parseInt(values[1]);
Since you're working with only primitives (and String) it seems that you'd like to avoid auto-boxing and unboxing if possible. That means you can't use generics. (Primitive types can't be used as type arguments.) It also seems as though you'd like to avoid unnecessary promotion (e.g. if you stored floats as doubles you'd preserve the original value, but lose the fact that it's actually a float).
A rather elaborate solution would be to create a set of PrimitivePair classes, one for each combination of primitive types that you want to store, along with a factory class for constructing them easily. For example, you might have the following three classes to store various pairs of primitives:
package primitivepair;
public class PrimitivePairStringInt
{
final String s;
final int i;
PrimitivePairStringInt(final String s, final int i)
{
this.s = s;
this.i = i;
}
public String getFirstValue()
{
return s;
}
public int getSecondValue()
{
return i;
}
}
package primitivepair;
public class PrimitivePairFloatDouble
{
final float f;
final double d;
PrimitivePairFloatDouble(final float f, final double d)
{
this.f = f;
this.d = d;
}
public float getFirstValue()
{
return f;
}
public double getSecondValue()
{
return d;
}
}
package primitivepair;
public class PrimitivePairCharByte
{
final char c;
final byte b;
PrimitivePairCharByte(final char c, final byte b)
{
this.c = c;
this.b = b;
}
public char getFirstValue()
{
return c;
}
public byte getSecondValue()
{
return b;
}
}
They would be created by the following factory class:
package primitivepair;
public class PrimitivePairFactory
{
public static PrimitivePairCharByte createPrimitivePair(final char c, final byte b)
{
return new PrimitivePairCharByte(c, b);
}
public static PrimitivePairFloatDouble createPrimitivePair(final float f, final double d)
{
return new PrimitivePairFloatDouble(f, d);
}
public static PrimitivePairStringInt createPrimitivePair(final String s, final int i)
{
return new PrimitivePairStringInt(s, i);
}
}
You can of course add more classes and factory methods for other combinations.
I wanted to make an abstract PrimitivePair class that would have the creation methods and method declarations for the getFirstValue() and getSecondValue() methods, but that would have required that return type covariance works for primitives, and I don't believe it does.
Java does not have a built-in Tuple type.
You might use the standard Map.Entry<K,V> but I would personally suggest Apache Commons Lang3's Tuple type if possible.

Mutable 4 dimensonal tuple in java

Is there a Java implementation for mutable 4 dimensional Tuple?
MutableTuple4<Intger, Integer, Double, Double> a;
a.setFirst(a.getFirst() + 1);
There is no built-in general purpose Tuple4 class, but you can easily write your own general purpose arbitrary length Tuple classes, and there are a number of implementations available to base code on such as apache.commons.MutableTriple (source code here).
There is also the javatuples library which provides Immutable tuples up to 10 elements in length that you could base your implementation on (although I've not used it personally). Perhaps you could ask yourself if you even need mutability?
In fact, as others have already mentioned, I would strongly question the validity of a mutable Object with arbitrary value types - it's usually better to actually encapsulate a specific concept in a class than just passing around "bags of values".
Caveats aside, here's an example implementation, based on the apache MutableTriple class mentioned above that could be built upon. As always, you need to be very cautious using mutable variables in multi-threaded environments: Do not consider this code in any way threadsafe (I generally prefer immutability over mutability wherever possible).
public class MutableTuple4<A, B, C, D> {
private static final long serialVersionUID = 1L;
public A first;
public B second;
public C third;
public D fourth;
public MutableTuple4(A a, B b, C c, D d) {
this.first = a;
this.second = b;
this.third = c;
this.fourth = d;
}
public A getFirst() {
return this.first;
}
public void setFirst(A first) {
this.first = first;
}
// remaining getters and setters here...
// etc...
#Override
public int hashCode() {
int hash = 3;
hash = 23 * hash + Objects.hashCode(this.first);
hash = 23 * hash + Objects.hashCode(this.second);
hash = 23 * hash + Objects.hashCode(this.third);
hash = 23 * hash + Objects.hashCode(this.fourth);
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Tuple<A, B, C, D> other = (Tuple<A, B, C, D>) obj;
if (!Objects.equals(this.first, other.first)) {
return false;
}
if (!Objects.equals(this.second, other.second)) {
return false;
}
if (!Objects.equals(this.third, other.third)) {
return false;
}
if (!Objects.equals(this.fourth, other.fourth)) {
return false;
}
return true;
}
}
There is, but it's specifically for vector math, and for Java3D in particular:
http://docs.oracle.com/cd/E17802_01/j2se/javase/technologies/desktop/java3d/forDevelopers/j3dapi/javax/vecmath/Tuple4d.html
Not intended for general purpose tupling. And it doesn't allow you to mix integers and doubles like your example shows.
Like JB Nizet says in the comment, classes are generally more appropriate.

Categories