I'm looking for an elegant way to use values in a Java enum to represent operations or functions. My guess is, since this is Java, there just isn't going to be a nice way to do it, but here goes anyway. My enum looks something like this:
public enum Operator {
LT,
LTEQ,
EQEQ,
GT,
GTEQ,
NEQ;
...
}
where LT means < (less than), LTEQ means <= (less than or equal to), etc - you get the idea. Now I want to actually use these enum values to apply an operator. I know I could do this just using a whole bunch of if-statements, but that's the ugly, OO way, e.g.:
int a = ..., b = ...;
Operator foo = ...; // one of the enum values
if (foo == Operator.LT) {
return a < b;
}
else if (foo == Operator.LTEQ) {
return a <= b;
}
else if ... // etc
What I'd like to be able to do is cut out this structure and use some sort of first-class function or even polymorphism, but I'm not really sure how. Something like:
int a = ..., b = ...;
Operator foo = ...;
return foo.apply(a, b);
or even
int a = ..., b = ...;
Operator foo = ...;
return a foo.convertToOperator() b;
But as far as I've seen, I don't think it's possible to return an operator or function (at least, not without using some 3rd-party library). Any suggestions?
Not only is this possible, it's used as an example in the frequently referenced Effective Java, Second Edition by Josh Bloch. I don't want to step on his copyright, will look for a similar example online...
Okay, the code I remembered is freely available at the website I linked earlier. Click "Download the code samples used in this book", then look at effective2/examples/Chapter6/Item30/Operation.java.
int a = ..., b = ...;
Operator foo = ...;
return foo.apply(a, b);
it is possible to do this if foo is object and Operator is base class and concrete operators are concrete classes that implement apply.
Related
I have a class OffbyOne where I declare an interface as a comparator called compare where I'm supposed to take two integers and return True if the difference between two integers is 1, and false if not.
Here is my code so far:
public static class OffbyOne {
public interface Compare {
int x;
int y;
if ((x-y) == 1) {
return true;
} else if ((y-x)==1) {
return true;
}
return false
public boolean equalChars(char x, char y); {
if (Compare(x,y) == true) {
return true;
}
return false;
}
I'm struggling to understand how comparators work in Java and what do I have to do. If anyone can please help me with this and then provide explanations for how it is supposed to be done, it would be great for me.
Thank you.
Comparator already exists in java - java.util.Comparator. It is something completely different from what you describe: Java's own comparator is a thing that you give 2 objects, and the comparator tells you which of the two 'comes earlier' in a sorting. Such an oracle is all you need to efficiently sort stuff.
It's allowed, but a bad idea, to name types the same as core java types. You can make your own String, which is different from java's own String in all ways (your String does not in any way replace java's string), it's just a confusing name, is all. You're doing the same thing with Comparator here. Bad idea. I'd call it OffByOne or similar.
declare an interface as a comparator called compare where I'm supposed to take two integers and return True if the difference between two integers is 1, and false if not.
This makes no sense whatsoever. You must have misunderstood the assignment. An interface describes the what and does not describe the how, whereas what you just said is describing the how. That's just not what interfaces do - they don't get to define the how. They only define the what. You're describing an implementation, not an interface.
public interface Compare {
int x;
int y;
if ((x-y) == 1) {
You can't stick code in types like this. You can stick only methods, fields, constructors, and other types in there. You can stick code in a method and then stick the method in a type, if you want. In addition, given that it is an interface, you can't stick code in one at all - interfaces define what a class can do, not how it does it (there is the default mechanism. That's definitely not what this assignments wants you to do so, so it doesn't apply here).
This would be an interface:
public interface DifferenceOfOne<T> {
public boolean isDifferenceOfOne(T a, T B);
}
This says: There is such a thing as a 'DifferenceOfOne' implementation for any given type. Such a class would implement the method isDifferenceOfOne, which takes in 2 parameters, both of that given type, and which then returns a boolean.
You can then make an implementation for the Integer type:
class IntDiffOfOne implements DifferenceOfOne<Integer> {
public boolean isDifferenceOfOne(Integer a, Integer b) {
return (a - 1 == b || b - 1 == a);
}
}
DifferenceOfOne<Integer> intDiffOfOne = new IntDiffOfOne();
Or in more common, modern java syntax:
DifferenceOfOne<Integer> intDiffOfOne = (a, b) -> (a - 1 == b || b - 1 == a);
And someone else can write a DiffOfOne implementation that, I dunno, tells you if any 2 LocalDate instances differ by exactly 1 day, perhaps, that would be a DifferenceOfOne<LocalDate>.
If this all sounds confusing to you - go back to whomever gave you this assignment, as either the assignment makes no sense, or you misheard/misunderstood it.
Let's say that I have function Object f(String a, String b) and I want to call two different functions that return Optional Strings to get the parameters for f Optional<String> getA() and Optional<String> getB(). I can think of two solutions but neither look all that clean, especially when you have even more parameters:
1:
return getA().flatMap(
a -> getB().map(
b -> f(a,b)).get()
2:
Optional<String> a = getA();
Optional<String> b = getB();
if(a.isPresent() && b.isPresent()) {
return f(a.get(), b.get());
}
Is there a cleaner way to do this?
You've just stumbled upon a concept called lifting in functional programming, that enables you to lift regular functions (e.g. A -> B) into new domains (e.g. Optional<A> -> Optional<B>).
There's also a syntactic sugar for flatMapping and mapping more comfortably called the do notation in Haskell and similar languages, and for comprehension in Scala. It gives you a way to keep the flow linear and avoid nesting (that you were forced to go through in your example 1).
Java, unfortunately has nothing of the sort, as its functional programming capabilities are meager, and even Optional isn't really a first-class citizen (no standard API actually uses it).
So you're stuck with the approaches you've already discovered.
In case you're curious about the concepts mentioned above, read on.
Lifting
Assuming you have:
public String f(A a, B b) {
return b + "-" + a;
}
With its Scala equivalent:
def f(a: A, b: B) = b + "-" + a
Lifting f into Option (same as Optional in Java) would look like this (using Scalaz library, see here for Cats)
val lifted = Monad[Option].lift2(f)
lifted is now a function equivalent to:
public Optional<String> f(Optional<A> a, Optional<B> b) {
if(a.isPresent() && b.isPresent()) {
return Optional.of(b + "-" + a);
}
return Optional.empty;
}
Exactly what you're looking for, in 1 line, and works for any context (e.g. List, not just Option) and any function.
For comprehension / Do notation
Using for comprehension, your example would look like this (I think, my Scala is weak):
for {
a <- getA();
b <- getB();
} yield f(a, b)
And again, this is applicable to anything that can be flatMapped over, like List, Future etc.
You could stream the arguments and apply the condition only once, but whether or not this is more elegant than your solutions is in the eye of the beholder:
if (Stream.of(a, b).allMatch(Optional::isPresent)) {
return f(a.get(), b.get());
}
I'm of the opinion that if there is no good way to use Optional, then there is no reason to try to use it anyway.
I find this to be cleaner and simpler than your option 2:
String a = getA().orElse(null);
String b = getB().orElse(null);
if(a != null && b != null) {
return f(a, b);
}
If you are sure that a and b are both present (as your final call to get in solution 1 seems to suggest), I think it is pretty straightforward:
return f(getA().orElseThrow(() -> new NoSuchElementException("a not present")),
getB().orElseThrow(() -> new NoSuchElementException("b not present")));
If you aren’t sure that both are present, I would prefer your solution 1. It exploits Optional the best. Only I would not call get at the end, but rather orElse or what makes sense in your situation, for example:
return getA()
.flatMap(a -> getB().map(b -> f(a,b)))
.orElse("Not both present");
In this question the author uses the following example:
#Override
public final OptionalInt max() {
return reduce(Math::max); //this is the gotcha line
}
So in this case it looks as if max() is a proxy for Math.max on the instance of this class. However there are no arguments passed to max, so does java 8 compile this to something like (Pseudo code):
#Override
public final OptionalInt max(Integer a, Integer b) {
//If neither a or b are null
return new OptionalInt.of(Math.max(a,b));
//Otherwise return empty because we can't compare the numbers
return OptionalInt.empty()
}
Also how would one write the javadoc for something like this?
So in this case it looks as if max() is a proxy for Math.max on the instance of this class. However there are no arguments passed to max, so does java 8 compile this to something like (Pseudo code):
#Override
public final OptionalInt max(Integer a, Integer b) {
//If neither a or b are null
return new OptionalInt.of(Math.max(a,b));
//Otherwise return empty because we can't compare the numbers
return OptionalInt.empty()
}
Not quite :). Let's start by figuring out what the reduce operator actually does. The documentation explains that it performs a reduction on a sequence of numbers by applying an algorithm that is logically equivalent to the following:
public OptionalInt reduce(IntBinaryOperator op) {
boolean foundAny = false;
int result = 0;
for (int element : [this stream]) {
if (!foundAny) {
foundAny = true;
result = element;
}
else {
result = op.applyAsInt(result, element);
}
}
return foundAny ? OptionalInt.of(result)
: OptionalInt.empty();
}
Seems simple enough. If you can tell it how to take two numbers and 'reduce' or 'combine' them into one, then reduce knows how to extend that logic to reduce an entire sequence into a single number. It handles the edge cases and the aggregation for you. All it needs from you is a function that takes in two numbers and gives it one back. That function should conform to the functional interface IntBinaryOperator.
A functional interface is an interface that is meant to describe a single function. Specifically, it describes the argument types and the return type. The rest is largely superfluous. The signature for an IntBinaryOperator looks like this:
int applyAsInt(int left, int right);
You can provide a function that conforms to this specification in several ways. Prior to Java 8, you might have done something like this:
stream.reduce(
new IntBinaryOperator() {
public int applyAsInt(int a, int b) {
return b > a ? b : a;
}
}
);
Java 8 gives us a shorthand form for functional interfaces called lambda expressions. These are a bit more concise, and while they are conceptually similar to anonymous inner classes, they're not quite the same thing.
stream.reduce((a, b) -> b > a ? b : a);
Both functions above are equivalent: they take in two numbers and return the larger of the two. As it turns out, every standard programming library has a function that does exactly the same thing. In Java, that function is Math.max. So rather than writing this logic myself, I can delegate to Math.max:
stream.reduce((a, b) -> Math.max(a, b));
But wait! All reduce wants is a function that takes two numbers and returns one. Math.max does that, so do I even need to wrap it in a lambda? It turns out I don't; I can tell reduce to just call Math.max directly:
stream.reduce(Math::max);
This says "I know you want a function, so I'm show you by name where to find one that's already been written". The compiler knows that Math.max conforms to the (int, int) -> int specification we need, so it emits some bytecode telling the VM how to 'bootstrap' it once it's needed. When the JVM hits your call to reduce, it calls a special method that generates a wrapper class implementing IntBinaryOperator that delegates to Math.max in its implementation of applyAsInt. It only performs this 'bootstrapping' step once. Since calling Math.max doesn't rely on anything other than the two numbers that get passed in, it can cache that implementation and use it the next time you wind up on this code path.
Pre Java 8, this would have been written as:
public MyMathInteface {
OptionalInt max(Integer a, Integer b);
}
public static final MyMathInterface reducing = new MyMathInterface() {
#Override
public OptionalInt max(Integer a, Integer b) {
return OptionalInt.of(Math.max(a, b));
}
};
#Override
public final OptionalInt max() {
return reduce(reducing);
}
Then reduce would be defined as:
public static OptionalInt reduce(MyMathInteface toReduce) {
return toReduce.max(someValueA, someValueB);
}
So to answer your question, no arguments are passed to Math::max, because those values are retrieved by the reduce function. They could be constants or they could be retrieved from some other place.
In any case, the use of the max method in this way is called a method reference, that is where you do SomeObject::method. That :: operator creates a method reference. It returns a function, but does not call the function. The user (reduce) is responsible for calling the function.
Which is faster and/or less resources consuming:
class Foo()
{
public int value;
}
This way?
public int doSomeStuff(Foo f)
{
return (f.value + 1);
}
public int doOtherStuff()
{
...
Foo f = new Foo();
int x = doSomeStuff(f);
...
)
or this way?
public int doSomeStuff(int v)
{
return (v + 1);
}
public int doOtherStuff()
{
...
Foo f = new Foo();
int x = doSomeStuff(f.value);
...
)
In both cases, "doSomeStuff" will not change nothing in foo class. It just needs to know the "value".
They both perform the same, the same sequence of operations occurs. Your main concern is maintainability and sensible design here. Think carefully about which methods need which data and design it properly.
If you do have issues, you can optimise later. But you should always optimise last.
In terms of resource consuming, it is exactly the same.
But the second option is clearly better in terms of programming because if doSomeStuff only needs value, then there is no point to passing f.
I don't think there is any performance difference at all. And Java compiler will optimize to the best one anyway...
Depends how often you're going to call doSomeStuff without calling doOtherStuff, but generally performance difference is negligible and if you only call doOtherStuff then they'll be equally performant.
Probably even better:
Decalre doSomeStuff() as a method of foo, and invoke: f.doSomeStuff()
It is much more readable and will be easier to maintain doing it so, since if you have a
sub class of foo: Bar, and you want to calculate things a bit different - all you have to do is override doSomeStuff() in Bar
You should prefer readability over micro optimizations - let the compiler take care of those for you.
code snap:
class foo() {
public int value;
public int doSomeStuff() {
return value + 1;
}
}
and:
public int doOtherStuff() {
...
foo f = new foo();
int x = f.doSomeStuff();
...
}
The difference between doing:
object.intvariable + 1
and
int + 1
is so negligible as to be irrelevant for real world apps. It's probably one or two more JVM opcodes to look up foo and find its value variable which is not worth mentioning. You'd never notice that unless you were trying to create a pseudo real-time app in Java (which is all but an exercise in futility).
However, that said, the way you are doing it is very bad. You should not be exposing value directly, but be using proper data encapsulation via getter and setter methods.
It does not matter from performance perspective.
The recommendation is: do not think about pre-mature optimization. Think about correctness and good design of your code.
For example your code
Does not follow naming conventions: class names must start with capital letter
Contains public fields. It is forbidden. Use bean notation (getters and setters).
Cannot be compiled (there is no type integer. Choose among int and Integer
My question is eerily similar to "Writing a generic class to handle built-in types" including being inspired by the fact of working on a class to handle operations on matrices.
Although that question was asked using C# and pointed to an article on Generic Operators.
I don't get it. Java Number does not have an add method so you can have a method like:
public Number myAdd(Number a, Number b){
return a.add(b);
}
So how do you handle a case where you want to be able to handle multiple types of Numbers in Java?
The fundamental problem is with the Java type system which is very primitive.
Since there is no notion of a sealed set of types in Java (nor is it possible for Java to infer the types like Haskell does) there is no way to make make a general Number + Number -> Number without trickery.
For primitives (and those objects like Integer which can be automagically mapped to them) types promotion and the + operation is part of the language. (And this is actual part of the problem: what should Number a + Number b return where a and b are of different types?)
If you really want this behavior you'll have to find (or create) your own custom class that either uses reflection or a series (of checks and) casts and such. Even if you use generics (remember that generics are type-erased) casting will need to be done.
I imagine these problems are part of the reason why Number is as bland as it is.
How good do you want the result to be? If the answer is "good enough, mostly", then this should be sufficent:
public Number myAdd(Number a, Number b){
return a.doubleValue() + b.doubleValue();
}
But if you want something that, say, matches the promotion semantics of Java primitives, you're probably going to have to write it yourself. And then you'll have to figure out what the rules are for all combinations of "non-standard" Number implementations, including BigDecimal, BigInteger, AtomicDouble, AtomicLong, everything in org.apache.commons.lang.mutable, and any random implementation that somebody might decide to write next Tuesday.
It's not clear what the right thing to do is in most of these cases -- converting everything to BigDecimal, for instance, is not an option if one of the arguments is Apache Commons' Fraction.ONE_THIRD; and besides, doing the conversion in a general way presents the same problems as doing the addition in a general way. But having an add() method on Number would require every Number implementation to handle all these cases -- and that's probably why it isn't there.
I don't get it. Java Number does not
have an add method ...
Suppose that java.lang.Number did have an add method or methods, how would you define its signature? How would you define its semantics? How would you deal with "mixed mode" arithmetic?
While it is no doubt possible to answer these questions and design an API, the result is likely to be tricky to use correctly. In addition, it is most unusual for an application to need to perform "representation agnostic" arithmetic. Usually you want / need explicit control over the way that arithmetic is performed and conversions happen. (The Java primitive type promotion rules are already difficult enough for people to get their heads around!!)
All in all, I think that Sun have done us a good service by not trying to support arithmetic in the Number API.
One way of implementing a generic add method is to let the left hand argument infer the return type.
package mixins;
import java.math.BigDecimal;
public class Numbers {
public static boolean isZ(Number n) {
return n instanceof Integer || n instanceof Long || n instanceof Short || n instanceof Byte;
}
public static boolean isR(Number n) {
return n instanceof Double || n instanceof Float;
}
public static BigDecimal add(BigDecimal a, Number b) {
if (b instanceof BigDecimal) {
return a.add((BigDecimal) b);
} else if (isZ(b)) {
return a.add(new BigDecimal(b.longValue()));
} else if (isR(b)) {
return a.add(new BigDecimal(b.doubleValue()));
}
throw new IllegalArgumentException("No valid big decimal translation for " + b.getClass());
}
public static Integer add(Integer a, Number b) {
return a + b.intValue();
}
public static Long add(Long a, Number b) {
return a + b.longValue();
}
public static Float add(Float a, Number b) {
return a + b.floatValue();
}
public static Double add(Double a, Number b) {
return a + b.doubleValue();
}
}
If this is implemented as static methods, you can use static imports.
import static mixins.Numbers.*;
public class Example {
public static void main(String[] args) {
BigDecimal fortytwo = new BigDecimal(42);
BigDecimal fiftyfive = add(fortytwo, 13);
System.out.println(fiftyfive);
}
}
You cannot add any two numbers, for the reasons other pointed out, but you can add numbers of same type, and the result will also be that same type.
You can create generic arithmetics in Java, with something like this:
interface Arithmetics<T> {
T add(T val1, T val2);
}
class IntegerArithmetics implements Arithmetics<Integer> {
Integer add(Integer val1, Integer val2) { return val1 + val2; }
}
//similarly DoubleArithmetics, BigIntegerArithmetics, ...
Generic Java Math library does exactly that for you.
Actually, I've been working on a generic "real" number class (called 'Value') for a while now, but more as a design exercise than anything; and I can see why it hasn't been done sooner.
First off, you have to have to have some basic rules to work by - I chose to use Java FP (IEEE-754) rules - which means you have have to allow for results like 'infinity' and 'NaN', even if the type doesn't actually support them; and things like reciprocals have proved surprisingly tricky. But I'm getting there, and it's been a fun journey.
One thing that helped me was deciding early on that I needed to deal with "identity" values - specifically 0, 1, and -1, along with -0, +/-infinity and NaN as special cases; the reason being that (for example) multiplication by any of them usually doesn't need any calculation at all.
x * 1 = x, x * NaN = NaN, x * 0 = 0 (or NaN), and x * +/-infinity = +/-infinity; and there are similar rules for division, addition and subtraction, which means you can eliminate a lot of dross quickly and consistently.
And that leaves implementers to only have to deal with cases that do need calculation.
Of course, not all types will support all identities, but if you make them methods, you can just throw an exception when either an operand or a result is "unsupported".
Hope it helps anyone else interested in giving it a bash, but it's not as simple it looks. :-)
Personally, I use BigDecimals for almost everything (but that is mainly because I work with currency values). They handle all numeric values of any size. Because of that, in my opinion they are a generic value and could be used as such in your hypothetical example instead of the Number abstract class. Everything can be turned into a BigDecimal, why not use it?
public BigDecimal myAdd(BigDecimal a, BigDecimal b) {
return a.add(b);
}
EDIT: To address BigBrothers comment below, you could always use the doubleValue() method to create your own generic method. The only problem with this is that you may lose precision in some rare cases where someone IS passing in a BigDecimal and it is larger than a Double.maxValue
public Number myAdd(Number a, Number b) {
return new BigDecimal(a.doubleValue() + b.doubleValue());
}
A BigDecimal is a Number, so returning one is of no consequence.