Java How to chain with Math class - java

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)));

Related

Does java cache method results?

If i have an immutable class like this:
public class MathClass {
private final int x;
public MathClass(int x) {
this.x = x;
}
public int calculateSomething() {
return Math.sqrt(x);
}
}
Does the jvm cache the result of calculateSomething() on the first call?
I have a more complicated calculation in the MathClass.
No it does not, only the object is stored within the cache
You could use your own caching solution, such as Spring's #Cacheable to store method results in cache
No, Java doesn't cache method results in general.
Some few methods of the Framework do this, but it's part of their implementation, e.g. Integer.valueOf(int).
c.f. JavaDoc:
This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range."
But with your implementation it would be easy to implement the "caching" by yourself: the class is immutable, that means the inputs don't change, so you can easily calculate the value on the first request and return the previously calculated value on subsequent requests:
public class MathClass {
private final int x;
private transient boolean calculated = false;
private transient int preCalcSomething;
public MathClass(int x) {
this.x = x;
}
public int calculateSomething() {
if (!calculated) {
preCalcSomething = Math.sqrt(x);
calculated = true;
}
return preCalcSomething;
}
}
I used the transient keyword here to mark that those two fields are not part of the "object state". Don't forget to exclude them from equals and hashCode calculations and maybe other state-depending methods!
If you are using an object instead of a primitive, I would use null as indicator for "not yet calculated" if that is a value that cannot be the actual result of the cached operation.
You could calculate it just once, and then return the result previously calculated.
public class MathClass {
private final int x;
private final int result;
public MathClass(int x) {
this.x = x;
this.result = Math.sqrt(x);
}
public int calculateSomething() {
return result;
}
}
The calculation will not be performed more than one time. This is not a cache but works as one in your scenario.

return method refference to stream

I have a class Care
class Car{
private int wheels;
private int doors;
...
public int getWheels(){ return wheels;}
public int getDoors(){ return doors:}
}
And I have a collection of the cars
List<Car> cars = ...
I want to calculate the average numbers of doors and windows in the collection. I could do this:
cars.stream().mapToInt(Car::getWheels).avg().orElse(0.0)
cars.stream().mapToInt(Car::getDoors).avg().orElse(0.0)
However, I want to create a dynamic function for this, for example:
public double calculateAvgOfProperty(List<Car> cars, String property){
Function<Car,Integer> mapper = decideMapper(property);
return cars.stream().maptoInt(mapper).avg().orElse(0.0);
}
public Function<Car,Integer> decideMapper(String ppr){
if( ppr.equals("doors") return Car::getDoors;
if( ppr.equals("wheels") return Car::getWheels;
}
However, .mapToInt() requires ToIntFunction<? super T> mapper as argument, but the method reference is Function<Car,Integer>, and casting does not work.
However when I directly pass the method reference, for example .mapToInt(Car::getDoors), it works.
How to cast correctly cast Function<Car,Integer> to required type then?
You should not cast a Function to a ToIntFunction as they are not associated (ToIntFunction does not extend Function). They are however both functional interfaces, so the method reference can also be inferred directly as a ToIntFunction.
There is an average() method defined in IntStream:
public double calculateAvgOfProperty(List<Car> cars, String property) {
ToIntFunction<Car> mapper = decideMapper(property);
return cars.stream().mapToInt(mapper).average().orElse(0.0);
}
public ToIntFunction<Car> decideMapper(String ppr){
if( ppr.equals("doors")) return Car::getDoors;
if( ppr.equals("wheels")) return Car::getWheels;
...
}
Do you mean to create a method like this:
private double calculateAvgOfProperty(List<Car> cars, Function<Car, Integer> function) {
return cars.stream().mapToDouble(function::apply)
.average()
.orElse(0.0);
}
and then you can only call:
double r1 = calculateAvgOfProperty(cars, Car::getWheels);
double r2 = calculateAvgOfProperty(cars, Car::getDoors);
I don't understand very well your question, but you can replace mapToDouble with mapToInt if you want.
I'm not sure what you're trying to achieve, but I'm sure, that you have quite a few compile time errors in your code:
Missing some closing braces in the decideMapper method;
You don't really return anything for the default case, from decideMapper;
calling some .avg() on IntStream, which is not available.

Java instanceof not match Double

I have a Value Class and there is an Object value in it. I want to use the value as String, Integer or Double.
The asDouble method controls instanceof value object. If it is not Double or Integer returns 0.
Generally it works but sometimes although it is Double returns 0;. I couldn't the reason of it.
When I debug I can see:
Here is my Value class
public class Value{
public Object value;
public Value(Object value) {
this.value = value;
}
public Double asDouble() {
if (this.value instanceof Integer || this.value instanceof Double) {
return Double.parseDouble(String.valueOf(this.value));
} else {
return 0.0;
}
}
}
Could anybody explain where did I go wrong
Short Answer: Details matter.
Some info: The value class instance variable (also-known-as property or member variable) is a class named Value.
Since the class Value is neither the Integer nor the Double class,
the else branch will always execute.
The Value class also has a member variable named value,
which,
in your example,
has a type of Double.
In the screen shot you included,
the Value object has its value member variable set to a "thing" which also has the type Value.
I know this because the dialog shows "value= Value (id:82)".
first at all, i agree with Ole V.V.s, killjoys and david as comments.
your screenshot shows a Value-Object holding another Value-Object in its value-property
the comments and a possible solution are summed up in the following example-class
public class Value {
// visibility should be private
private final Object value;
// to be more type-save
// and to restrict
// this.values instance-type to Double, Integer and/or String
// provide three public constructors
public Value(final Double value) {
this.value = value;
}
public Value(final Integer value) {
this.value = value;
}
public Value(final String value) {
this.value = value;
}
public double asDoublePrimitive() {
if ((this.value instanceof Number)) {
return ((Number) this.value).doubleValue();
}
return 0.0;
}
public Double asDoubleObject() {
if ((this.value instanceof Number)) {
return Double.valueOf(((Number) this.value).doubleValue());
}
return Double.valueOf(0.0);
}
}
be aware that neither your nor my code consider the case that this.value is an instanceof String
instanceof check applies to full class definiton which includes the ClassLoader that loaded the class. Probably this.value was loaded by different ClassLoader and the check fails. You can confirm by trying:
ClassLoader cl1 = this.value.getClass().getClassLoader()
ClassLoader cl2 = Double.class.getClassLoader();
if (cl1.equals(cl2)) {
...
}
Although this can get even more trickier with parent-child relationships between ClassLoader objects this answer provides a good example when instanceof fails.
The other options is that your Double is not a java.lang.Double but that would be surprising.

Why getting unable to cast to type when casting generic method args to specific one?

I have written a java code for scientific calculator and also written jUnit test for it.Below is the method for calculating cubeRoot.
public <T> Double cubeRoot(T number){
Double result= Math.cbrt((Double)number);
return Math.abs(result);
}
Method returns proper result integer and double types,but when i invoke method for decimal,argument i pass is double type.Following are the JUint Test for above method.
public void testCalculateCubeRootWhenNegative(){
Integer number=-64;
assertEquals(-4.0,sci.cubeRoot(number));
}
public void testCalculateCubeRootOfdecimal(){
Double number=0.40;
assertEquals(0.736,sci.cubeRoot(number));
}
And this the interface i am using
public interface iScientific extends iMaths {
<T>Double squareRoot(T number);
<T>Double cubeRoot(T number);
Unable to find solution for getting error "java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double"
You are trying do to something like this:
Integer i = Integer.valueOf(0);
Double d = (Double) i;
This does not work because i is not an instance of Double.
I suggest to change your cubeRoot method to accept a Number (the base class of both Integer and Double):
public Double cubeRoot(Number number) {
Double result = Math.cbrt(number.doubleValue());
return Math.abs(result);
}
Again i have do some more code change to make the code error free as initially error persist.Check the correction i have made and do suggest for more refactoring of code.
public Double cubeRoot(Number number){
DecimalFormat df=new DecimalFormat("#.####");
double result= Math.cbrt(number.doubleValue());
return Double.valueOf(df.format(result));
}
And the following test passed.
public void testCalculateCubeRootWhenNegative(){
Integer number=-64;
assertEquals(-4.0,sci.cubeRoot(number));
}
public void testCalculateCubeRootOfdecimal(){
Double number=0.40;
assertEquals(0.7368,sci.cubeRoot(number));
}

Incorrect Casting

For some reason I am getting a precision error when I try to compile my code. The precision error comes in the return of my second method where I am trying to calculate the circumference. What am I doing incorrectly?
public class Methods2
{
public static final double PI = 3.14;
public static double calcCirc(double x)
{
return PI*x;
}
public static int calcCirc(int x)
{
return (2*(double) x)*PI;
}
public static void main(String[]args)
{
System.out.println(calcCirc(10.2));
System.out.println(calcCirc(4));
}
}
You are attempting to return a double value in a method declared to return an int. Java won't let you implicitly narrow your value like that.
If you're okay with the loss of precision, then explicitly cast the value to int -- Java will let you do that.
return (int) ((2*(double) x)*PI);
However, I would change the method to return double instead, not to lose precision:
public static double calcCirc(int x)
... as you already did with your other calcCirc method.
Both versions of calcCirc() ought to return doubles.
Also, side note--consider using different method names since they accept inputs that differ not only in type but also in semantics.
E.g. calcCircFromRadius(double radius), calcCircFromDiameter(double diameter). There's not really a reason to take an int as an input type here since Java will automatically cast ints to doubles for you.
try
public static int calcCirc(int x){
return (int)((2*x)*PI);
}

Categories