Method Enum isBigger() - java

I am trying to write a method in a Java enum: isBigger(Valoration val), which returns true if if the current rating is bigger than one that is passed as parameter throwing the exception ValorationNoValued if the valuations
compared (or both) is NO_VALUED.
public enum Valoracion {
NO_VALUED(0),
SO_BAD(0),
BAD(2),
OK(4),
GOOD(6),
EXCELENT(8),
WOW(10);
....
public boolean isBigger(Valoration val) throws ValorationNoValued {
if (val == NO_VALUED) {
throw new ValorationNoValued("message");
}
else {
return val.getValor() > this.valor;
}
}
}
I want to know if the current rating is NO_VALUED, but I don't know how.

You can always refer the the “current object” via this be it an enum or not. But…
It seems, your enum has a method getValor() to return the numerical value. Then it would be much cleaner to intercept the exceptional state there rather than in the comparison method:
public enum Valoracion {
NO_VALUED (0) {
#Override int getValor() {
throw new ValorationNoValued("message");
}
},
SO_BAD (0),
BAD(2),
OK (4),
GOOD (6),
EXCELENT (8),
WOW (10);
....
int getValor() {
return valorValue;
}
public boolean isBigger(Valoration val) throws ValorationNoValued {
return val.getValor()>this.getValor();
}
This way, no conditionals are needed and the symmetry between a.isBigger(b) and b.isBigger(a) comes for free.
If you prefer conditionals over overriding the method, you may still implement the getValor() method as
int getValor() {
if(this==NO_VALUED) throw new ValorationNoValued("message");
return valorValue;
}
without the need to care for two sides in the isBigger method.

Compare this:
If (this == NO_VALUED) {

Related

Compare by multiple methods in java compareTo? [duplicate]

This question already has answers here:
How to compare objects by multiple fields
(23 answers)
Closed 3 years ago.
I don't think that's the best way to word that title but I can't think of a better way to word it. Here's my problem: I have to write a method that compares in several different ways. If the last names are the same, I then need to compare by first name. If the first names are the same, then I need to sort by section. What would be the most effective way to sort a data structure in this hierarchy? Here's what I've currently got and I think I understand why it doesn't work but I can't come up with a different way to write this function:
//Student class structure, each field has a public get/set method
public class Student implements Comparable<Student>
{
private String fname;
private String lname;
private int section;
}
//My current compareTo method
#Override
public int compareTo(Student s)
{
/*
-compare by last name
-if the same, compare by first name
-if the same, compare by section
*/
String slast = s.getLastName();
if(lname.compareTo(slast) == 0)
{
String sfirst = s.getFirstName();
if(fname.compareTo(sfirst) == 0)
{
int sclass = s.getSection();
return Integer.compare(section, sclass);
}
else
{
return fname.compareTo(sfirst);
}
}
else
{
return lname.compareTo(slast);
}
}
You can create a Comparator for your Student class this way:
Comparator<Student> comparator = Comparator
.comparing(Student::getLastName)
.thenComparing(Student::getFirstName)
.thenComparing(Student::getSection);
And then use this comparator (instead of implementing Comparable interface) to sort a list with Student objects, or to create a TreeMap with these objects:
Collections.sort(listOfStudents, comparator);
TreeMap<Student> mapOfStudents = new TreeMap<>(comparator);
You don't have to use getters or setters if you're overriding compareTo. You can also forgo the else/return statements since they're terminal return statements, and just use return.
#Override
public int compareTo(Student s) {
if (lname.compareTo(s.lname) == 0) {
if (fname.compareTo(s.fname) == 0) {
return section.compareTo(s.section);
}
return fname.compareTo(s.fname);
}
return lname.compareTo(s.lname);
}
Your code looks correct to me.
What would be the most effective way to sort a data structure in this
hierarchy?
Well, it's worth mentioning that you are potentially doing the first two comparisons (first name and last name) multiple times
if(lname.compareTo(slast) == 0)
{
//...
}
else
{
return lname.compareTo(slast);
}
It should be fairly obvious that you are doing lname.compareTo(slast) twice. You can store the result in a variable instead.
int lastNameComparison = lname.compareTo(slast);
if(lastNameComparison == 0)
{
//...
}
else
{
return lastNameComparison;
}
It is a matter of style, but I would not bother to store the result of getters into variables. Just call them when you need them.
Combining both of the above points, you get:
int lastNameComparison = lname.compareTo(s.getLastName();
if (lastNameComparison == 0)
{
int firstNameComparison = fname.compareTo(s.getFirstName());
if (firstNameComparison == 0)
{
return Integer.compare(section, s.getSection());
}
else
{
return firstNameComparison;
}
}
else
{
return lastNameComparison;
}
The nesting is quite ugly and if we need to add another criteria, it would get even worse.
We can solve that by inverting the conditions and using multiple return statements.
int lastNameComparison = lname.compareTo(s.getLastName());
if (lastNameComparison != 0) return lastNameComparison;
// Last names must be equal
int firstNameComparison = fname.compareTo(s.getFirstName());
if (firstNameComparison != 0) return firstNameComparison;
// First names must be equal
return Integer.compare(section, s.getSection());
I would personally use the declarative style of writing this, but if this code is for an assignment, that is likely not what they are expecting.

An implementation of Optional for empty Strings

One of the best things about Optional is it saves all the boilerplate checking for null values in a long chain:
Optional.ofNullable(myService.getSomething())
.map(secondService::fetch)
.map(thirdService::fetchAgain)
// And so forth...
At any point the Optional will jump onto the 'empty' track if map returns a null.
It would be great if something similar could be done for Strings instead of having to check them for String::isEmpty every time:
Optional.ofNullable(entity.getName())
.filter(String::isEmpty)
.map(Utils::performSomeOperation)
.filter(String::isEmpty)
.or(service::getMostCommonName)
.filter(String::isEmpty)
.orElse("Bob");
Something like this:
OptionalString.ofEmptyable(entity.getName())
.map(Utils::performSomeOperation)
.or(service::getMostCommonName)
.orElse("Bob");
The key logic in Optional happens in ofNullable when it calls its check for value == null. Theoretically you could apply any sort of logic in there:
MagicalOptionalString(StringUtils::isNotBlank).ofEmptyable(entity.getName())
.map(Utils::performSomeOperation)
.or(service::getMostCommonName)
.orElse("Bob");
However, Optional is final, preventing any straightforward way of extending this behaviour. So is there an existing, robust implementation of this out there already?
Trying out a few things to resolve what you were aiming at, and realizing that I would second the thought from VGR as implementing such a use case is a lot of extra work as compared to using the existing methods.
Yet, few details that I could add to after spending some time looking over the implementations -
As a utility, you could implement a static implementation which verifies for both null and isEmpty condition for a string input and returns Optional accordingly. The code could look something like -
private static Optional<String> ofEmptyable(String string) {
return isNullOrEmpty(string) ? Optional.empty() : Optional.of(string);
}
private static boolean isNullOrEmpty(String target) {
return target == null || target.isEmpty();
}
this could then replace the usage of the ofNullable which specifically checks for null(the primary purpose of Optional).
Since the expectations in your problem statement were to actually handle the cases per method(map/or/orElse) call as in the optional, one approach similar to OptionalInt could be to implement a custom OptionalString as -
public final class OptionalString {
private static final OptionalString EMPTY = new OptionalString();
private final boolean isPresent;
private final String value;
private OptionalString() {
this.isPresent = false;
this.value = "";
}
private static OptionalString empty() {
return EMPTY;
}
private boolean isPresent() {
return isPresent;
}
private OptionalString(String value) {
this.isPresent = true;
this.value = value;
}
public static OptionalString of(String value) {
return value == null || value.isEmpty() ? OptionalString.empty() : new OptionalString(value);
}
public OptionalString map(Function<? super String, ? extends String> mapper) {
return !isPresent() ? OptionalString.empty() : OptionalString.of(mapper.apply(this.value));
}
public OptionalString or(Supplier<String> supplier) {
return isPresent() ? this : OptionalString.of(supplier.get());
}
String orElse(String other) {
return isPresent ? value : other;
}
public String getAsString() {
return Optional.of(value).orElseThrow(() -> new NoSuchElementException("No value present"));
}
}
which could be further implemented for your use case in the following manner -
String customImpl = OptionalString.of(entity.getName())
.map(OptionalStringTest::trimWhiteSpaces) // OptionalStringTest is my test class name where 'trimWhiteSpaces' operation on String resides
.or(service::getMostCommonName)
.orElse("learning");
System.out.println(String.format("custom implementation - %s", customImpl));
where
private static String trimWhiteSpaces(String x) {
return x.trim();
}
Note - Honestly, I couldn't find the rationale behind not having an OptionalString class upfront in the JDK (the reason why I am stating this is because I suspect there definitely must have been a thought behind it), I believe its just that the radius of my reach is much smaller and I would expect someone credible to add to the details here. IMHO, it seems more like almost all of what you desire is right there using the Optional<String> and which takes us back to the starting of the loop.
For anyone working in Kotlin, this is really easy to do:
class NonEmptyString private constructor(val Email: String) {
companion object Factory {
operator fun invoke(value: String?): T? = value?.let { if (it.isNotEmpty()) NonEmptyString(value) else null }
}
}
The "static" invoke function conditionally creates a new object depending on whether it's valid or not. And allows you to call it like a constructor (NonEmptyString(value)). The private constructor forces you to use the invoke method.
Because this returns a null if it's not valid, and Kotlin has null-safety built in, it can be really easy to chain. Adding map or flatMap functions is then pretty straight-forward.
See this Code Review question for a more comprehensive, generalisable example I wrote.

Why have a cast in a compareTo(Object)

public int compareTo(Object x) {
Task other = (Task)x;
if (other.priority == this.priority) {
System.out.println("Each task has the same priority level.");
return 0;
} else if (other.priority > this.priority) {
System.out.println(other.priority + "\n" + this.priority);
return -1;
} else {
System.out.println(this.priority + "\n" + other.priority);
return 1;
}
}
That's the code I have for a programming assignment for class. I'm not sure why I use Task other = (Task)x; or what it's doing here. The rest I understand. If anyone has a quick explanation of what that's actually doing here I would be greatful. Thank you!
You are casting Object x to Task other - Object and Task are different types, so you need the cast so you can treat x as the expected type (and get to it's fields).
Normally in compareTo() you would first have something like if (x instanceof Task) before blindly casting it - if you don't and the types are different then things will crash)
The method signature takes an Object type object so in order to reference the variable priority within the object passed in, it has to do a cast to the Task object as the variable only exists within the Task class.
Personally though, I would think this was bad practice as you do not know what sort of object is being passed in (any class subclassing Object can be passed in) so a instance of check would not go amiss less you want to run into a runtime error of a ClassCastException.
Alternatively, you could use generics to specify what sort of object you want to compare to. So rather than doing this...
public class Task implements Comparable {
private int priority = 1;
#Override
public int compareTo(Object o) {
if (o instanceof Task) {
Task t = (Task) o;
return this.priority < t.priority;
}
return -1;
}
}
...you could do this...
public class Task implements Comparable<Task> {
private int priority = 1;
#Override
public int compareTo(Task t) {
return this.priority < t.priority;
}
}

calling function should return default value, if object (or any function result) is null

Is it possible to wrap following code in a reusable function?
EDIT: this is just an example, I want a working solution for ALL recursion depths
what I want is that following code is generated:
if (MyObject o == null ||
o.getSubObject() == null ||
o..getSubObject().getSubSubObject() == null /*||
... */)
return defaultValue;
return o.getSubObject().getSubObject()/*...*/.getDesiredValue();
by calling something like
Object defaultValue = null;
Object result = NullSafeCall(o.getSubObject().getSubObject()/*...*/.getDesiredValue(), defaultValue);
The seond code block is just an idea, I don't care how it looks like, all I want is that I, if desired, can avoid all the null checks before calling a deeper function...
Injection could do this propably, but is there no other/easier solution? Never looked at injection before yet...
EDIT2: example in another language: http://groovy.codehaus.org/Operators#Operators-SafeNavigationOperator
Not really, any code you would write this way would look horrible and/or use very slow reflection. Unless you use an actual Java preprocessor that can understand and change the code you've written.
A better (but associated with quite a bit of refactoring) approach would be to make sure that the values in question cannot possibly be null. For example, you could modify the individual accessors (getSubObject(), getDesiredValue()) to never return null in the first place: make them return default values. The accessors on the default values return default values in turn.
Java8 helps to get the closest you'll get to your syntax with decent performance I suspect;
// Evaluate with default 5 if anything returns null.
int result = Optional.eval(5, o, x->x.getSubObject(), x->x.getDesiredValue());
This can be done with this utility class;
class Optional {
public static <T, Tdef, T1> Tdef eval(Tdef def, T input, Function<T,T1> fn1,
Function<T1, Tdef> fn2)
{
if(input == null) return def;
T1 res1 = fn1.apply(input);
if(res1 == null) return def;
return fn2.apply(res1);
}
}
Sadly, you'll need a separate eval() defined per number of method calls in the chain, so you may want to define a few, but compile time type safe and reusable with just about any calls/types.
You can do something like this
public static Object NullSafeCall(MyObject o,Object defaultValue){
if ( o == null || o.getSubObject() == null)
{
return defaultValue;
}
else
{
return o.getSubObject().getDesiredValue();
}
}
Now you can call this method as follows
Object result = NullSafeCall(o, defaultValue);
i would suggest just replace
Object result = NullSafeCall(o.getSubObject().getDesiredValue(), defaultValue);
by the
Object result = (o == null || o.subObject == null) ? defaultVlue : o.getSubObject().getDesiredValue();
Create method only if you can reuse it......
What you want is not possible. It is essential to understand that using this syntax: Object result = NullSafeCall(o.getSubObject().getSubObject() ...); the part of o.getSubObject().getSubObject() will be evaluated before any control passes to the function/method thus throwing the exception.
It is required to have some type of context before executing such code. The closest to this I could think of, can be done using anonymous inner classes like the example below:
// intended to be implemented by an anonymous inner class
interface NullSafeOperation<T> {
public T executeSafely();
};
// our executor that executes operations safely
public static class NullSafeExecutor<T> {
public NullSafeExecutor() {}
public T execute(T defaultValue, NullSafeOperation<T> nso) {
T result = defaultValue;
try {
result = nso.executeSafely();
} catch(NullPointerException e) {
// ignore
}
return result;
}
// utility method to create a new instance and execute in one step
public static <T> T executeOperation(T defaultValue, NullSafeOperation<T> nso) {
NullSafeExecutor<T> e = new NullSafeExecutor<T>();
T result = e.execute(defaultValue, nso);
return result;
}
}
public static void main(String[] args) {
final String aNullString = null;
String result = NullSafeExecutor.executeOperation("MyDefault", new NullSafeOperation<String>() {
#Override
public String executeSafely() {
// trying to call a method on a null string
// it will throw NullPointerException but it will be catched by the executor
return aNullString.trim();
}
});
System.out.println("Output = " + result); // prints: Output = MyDefault
}

Most efficient way to prevent an infinite recursion in toString()?

To string on a collection can get into a infinite loop if somewhere in the graph of collected items is a reference back to itself. See example below.
Yes, good coding practices should prevent this in the first place, but anyway, my question is: What is the most efficient way to detect a recursion in this situation?
One approach is to use a set in a threadlocal, but that seems a bit heavy.
public class AntiRecusionList<E> extends ArrayList<E> {
#Override
public String toString() {
if ( /* ???? test if "this" has been seen before */ ) {
return "{skipping recursion}";
} else {
return super.toString();
}
}
}
public class AntiRecusionListTest {
#Test
public void testToString() throws Exception {
AntiRecusionList<AntiRecusionList> list1 = new AntiRecusionList<>();
AntiRecusionList<AntiRecusionList> list2 = new AntiRecusionList<>();
list2.add(list1);
list1.add(list2);
list1.toString(); //BOOM !
}
}
When I have to iterate over risky graphs, I usually make a function with a decrementing counter.
For example :
public String toString(int dec) {
if ( dec<=0 ) {
return "{skipping recursion}";
} else {
return super.toString(dec-1);
}
}
public String toString() {
return toString(100);
}
I won't insist on it, as you already know it, but that doesn't respect the contract of toString() which has to be short and predictable.
The threadlocal bit I mentioned in the question:
public class AntiRecusionList<E> extends ArrayList<E> {
private final ThreadLocal<IdentityHashMap<AntiRecusionList<E>, ?>> fToStringChecker =
new ThreadLocal<IdentityHashMap<AntiRecusionList<E>, ?>>() {
#Override
protected IdentityHashMap<AntiRecusionList<E>, ?> initialValue() {
return new IdentityHashMap<>();
}
};
#Override
public String toString() {
boolean entry = fToStringChecker.get().size() == 0;
try {
if (fToStringChecker.get().containsKey(this)/* test if "this" has been seen before */) {
return "{skipping recursion}";
} else {
fToStringChecker.get().put(this, null);
entry = true;
}
return super.toString();
} finally {
if (entry)
fToStringChecker.get().clear();
}
}
}
You can create toString which takes an identity hash set.
public String toString() {
return toString(Collections.newSetFromMap(new IdentityHashMap<Object, Boolean>()));
}
private String toString(Set<Object> seen) {
if (seen.add(this)) {
// to string this
} else {
return "{this}";
}
}
I recommend using ToStringBuilder from Apache Commons Lang. Internally it uses a ThreadLocal Map to "detect cyclical object references and avoid infinite loops."
The problem is not inherent to collections, it can happen with any graph of objects that have cyclic references, e.g., a doubly-linked list.
I think that a sane policy is: the toString() method of your class should not call toString() of its children/referenced if there is a possibility that it's part of a object graph with cycles. Elsewhere, we could have a special methods (perhaps static, perhaps as an auxiliary class) that produces a string representation of the full graph.
You could always keep track of recursion as follows (no threading issues taken into account):
public static class AntiRecusionList<E> extends ArrayList<E> {
private boolean recursion = false;
#Override
public String toString() {
if(recursion){
//Recursion's base case. Just return immediatelly with an empty string
return "";
}
recursion = true;//start a perhaps recursive call
String result = super.toString();
recursion = false;//recursive call ended
return result;
}
}
The simplest way: don't call toString() on the elements of a collection or a map, ever. Just print a [] to indicate that it's a collection or map, and avoid iterating over it entirely. It's the only bullet-proof way to avoid falling in an infinite recursion.
In the general case, you can't anticipate what elements are going to be in a Collection or Map inside another object, and the dependency graph could be quite complex, leading to unexpected situations where a cycle occurs in the object graph.
What IDE are you using? because in Eclipse there's an option to explicitly handle this case when generating the toString() method via the code generators - that's what I use, when an attribute happens to be a non-null collection or map print [] regardless of how many elements it contains.
If you want to go overboard, you could use an aspect that tracks nested collections whenever you call toString().
public aspect ToStringTracker() {
Stack collections = new Stack();
around( java.util.Collection c ): call(String java.util.Collection+.toString()) && target(c) {
if (collections.contains(c)) { return "recursion"; }
else {
collections.push(c);
String r = c.toString();
collections.pop();
return r;
}
}
}
I'm never 100% on syntax without throwing this into Eclipse, but I think you get the idea
maybe you could create an Exception in your toString and leverage on the stacktrace to know where you are in the stack, and you would find it there are recursive calls.
Some framework does this way.
#Override
public String toString() {
// ...
Exception exception = new Exception();
StackTraceElement[] stackTrace = exception.getStackTrace();
// now you analyze the array: stack trace elements have
// 4 properties: check className, lineNumber and methodName.
// if analyzing the array you find recursion you stop propagating the calls
// and your stack won't explode
//...
}

Categories