Best approach to refactor this java snippet - java

I was told it is not a good style to call potentially costly methods for boolean expressions (getSupercategories()).
private final SuperCategoriesResolver<ProductModel> catResolver = new SuperCategoriesResolver<ProductModel>() {
#Override
public Set<CategoryModel> getSuperCategories(final CategoryModel item) {
return item == null || item.getSupercategories() == null ? Collections.EMPTY_SET
: new LinkedHashSet<CategoryModel>(
item.getSupercategories());
}
};
As well that getSupercategories() is potentially dangerous since it's backed by a relation attribute which might not be coming from local data members (item is sent as a parameter to a public method in this class and after wards is sent to getSuperCategories() which is overriden in the same class when declaring catResolver).
Is this a better approach to tackle the argument above?
private final SuperCategoriesResolver<ProductModel> catResolver = new SuperCategoriesResolver<ProductModel>() {
#Override
public Set<CategoryModel> getSuperCategories(final ProductModel item) {
if (item != null) {
Set<CategoryModel> superCategories = (Set<CategoryModel>) item
.getSupercategories();
if (superCategories != null)
return superCategories;
}
return Collections.EMPTY_SET;
}
};
Where I first verify that item is not null. if it is, then a return empy_set if not then I called the costly method and get the collection and just if it is not null return the collection with elements.
Thank u very much for your advice.

It is likely to get more efficient to call getSupercategories() once instead of twice if it does any computation.
Do you need to return a copy of this set? You do in the first example but not the second.

Second approach is indeed faster because there is only one call to the getSupercategories method if item is not null. However, in your second approach, you no longer create a LinkedHashSet instance -- which means it will behave differently (though faster).
This sounds more like performance optimization as opposed to refactoring. Usually when you refactor something, there is a "factor" in there somwhere, that trims the code down by eliminating redundancies.

Nulls are your problem. Can you make a refactoring to push nulls away?
For example, you could refactor your code to make item.getSuperCategories never return null? Or do you need to distinguish between the empty set and null?
Similarly, why are you passing null into this method? If you can eliminate that scenario then the code just becomes a one liner.

Related

Elegant way to return variable before new variable assignment?

This might sound like a dumb question, because it might be no other way to do this. After designing my own list, this sort of "issue" came up in multiple occasions. To clarify, I have a problem with returning a cached variable after assigning new value to the original variable. Here's an example:
public T next() {
final Node<T> thisNode = posNode;
posNode = posNode.getNext();
return thisNode.getData();
}
This might seem like a non-issue, but occasionally multiple variables has to be cached before returning a valid value. I do not really like it, because personally I think it reduces the code's readability, especially when caching multiple variables.
Is there another way to write this code while maintaining its functionality? Basically a way to assign a new value to a variable after the return statement:
public T next() {
return posNode.getData();
posNode = posNode.getNext();
}
Thanks! :)
The second way is not possible as the code is not reachable after return. And your first way is the best way far you to achieve what you are looking for and it is not code smell. Often they refer as temp variables. Use them and better convey a message to the code reader by better naming convention. For ex tempPosNode
An elegant (but with some cognitive dissonance) option is a dummy method.
public static <T> T first(T first, Object... theRest) {
return first;
}
public T next() {
return first(posNode.getData(), posNode = posNode.getNext());
}
You can use a finally block to execute it, but it will execute even after exceptions:
public T next() {
try {
return posNode.getData();
} finally {
posNode = posNode.getNext();
}
}

Efficient null check for a compound object in Java [duplicate]

This question already has answers here:
is there a Java equivalent to null coalescing operator (??) in C#? [duplicate]
(5 answers)
Null check chain vs catching NullPointerException
(19 answers)
Closed 6 years ago.
A program creates a JDialog panel with multiple tabs. One of the tabs has several tables. A JTable has adjustable column width. This tab is generated under different conditions. Sometimes from the state tab is null, sometimes tab exists, but the table is null. Sometimes user haven't resized the column yet.
I am looking for a method to save the columnWidth value if user resized the column. Checking for null seems bulky in this situation:
jpanel.tab.table.width
the best method I can find is:
if( jpanel!=null &&
jpanel.jtab!=null &&
jpanel.jtab.jtable!=null && ...
Is there a better way to do this null check?
I saw this question:
is there a Java equivalent to null coalescing operator (??) in C#?
It doesn't list a solution and is quite old (Java 6-7 time). I was hoping this feature was added in later releases.
There's no way to do exactly what you want.
However, you can just throw everything into a try statement:
try {
myItem = bundle.category.subcategory.item;
}
catch(NullpointerException ignored) {}
Note that this looks very hacked, and it's rather poor coding practice. Your current solution is probably the best approach in terms of clarity.
Edit: I tried posting another Anwser but the button is greyed out, so I'll put it here:
Feels like repeating same code many times, when you should use a for loop
You can indeed use a for loop, but that will invovle Reflection and much boilerplate code. Imagine something like this:
static boolean checkDeepNull(Object root, String... attributes) throws NoSuchFieldException, IllegalAccessException {
Object currentAttribute = root;
for(int attr = 0; currentAttribute != null && attr < attributes.length; attr++){
Field nextField = currentAttribute.getClass().getField(attributes[attr]);
Object nextAttribute = nextField.get(current);
if(nextAttribute == null) return false;
currentAttribute = nextAttribute;
}
return true;
}
How to use it: if(checkDeepNull(bundle, "category", "subcategory", "item"))
You could have an interface which determines nullability:
public interface Nullability {
public boolean hasNulls();
}
And then simply have the parent call any children like so:
public boolean hasNulls() {
return this.bundle == null || bundle.hasNulls();
}
//in bundle
public boolean hasNulls() {
return this.category == null || category.hasNulls();
}
Regardless, if you have to nullcheck everything, you're going to be doing a lot of boilerplate code if you don't provide a means of iteration. That's what you should really focus on.
On a personal level, I disagree heavily with exposing fields like that. It's a very easy way to lead to more headaches and errors in design.
The short answer is no.
Can you redesign bundle so that it is always fully constructed? I.e., if bundle != null, then category, subcategory and item always exist? This could also help with concurrency issues. Basically, if nulls give you problems, where possible, don't allow these fields to be null.
Another option is the Null Object Pattern. Basically, you have a "default" implementation of Bundle which always return getCategory() that always returns a value for getSubcategory(), but ultimately the call to getItem() returns null or something to indicate "nothing". This is a great pattern but requires some work.
I hesitate to suggest it, but it is rare for any of the items to be null, at some point it may be faster and clearer to just catch the NPE, but this style should really be avoided. And it is a definite code smell that your design is poor. Avoid it if at all possible.
try {
return foo.bar.bap.zaz.blah.blah;
}
catch (NullPointerException ignored) {
return null;
}

How do I access the first non null term of a List in Java?

So I have a method (of which I can't change the parameters, or else this could have been made easier through HashMaps...more on this later), that passes an item as a parameter. Now I have a list of instances from this other class, of which one of its attributes is of the same type of this item, and I want to find the instances in the list which correspond to this item (of which there should be only one). This is what I did to find this:
List<Instance> instances = ...
public static void checkItems(Item i) {
List<Instance> n = new ArrayList<>();
instances.forEach(p -> n.add(p.i == i ? p : null));
Instance currentInstance = n.get(0);
//Instance currentInstance = instances.stream().filter(p -> p.i == i).collect(Collectors.toList()).get(0);
}
You'll probably notice two things straight up:
I used a conditional operator which adds a null value to the list when the condition isn't passed
My commented code which was another attempt to solve this issue
So in the first case, I put null because it requires you to put something, and a null value is probably easier to work with, which is why the question arises: How do I access the first non-null value in a list (without resorting to iterating over the entire list to find it...)?
You may notice that I just assign the first value of the list with n.get(0) to currentInstance, because I know that only one value will have passed the test. However, due to some other code that I apply to currentInstance, this value cannot be null.
Just a note on the second point: the way I tried to solve it with streams actually works exactly as planned, except that for some reason the list of instances recovered is not a direct copy of the original instances. This resulted in the values of some of the attributed to have been reset to default values, therefore rendering this method useless.
EDIT: I just wanted to mention that the streams method wasn't working because of some silly mistake that I made in another class, there was nothing wrong with the code so I'll be using that bit to solve my problem :D
If you know that only one p passes the test, I don't know what the point of creating a list with a load of null values plus p is.
Your problem seems to stem from wanting to use forEach. In my opinion, you should almost always use a for loop in preference to forEach. With a simple for loop you can just use break when the item is found.
In detail:
Instance p = null;
for (Instance q : instances) {
if (q.i == i) {
p = q;
break;
}
}
if (p == null)
throw new IllegalStateException(); // It wasn't there.
// Do something with p.
You could do it this way:
Instance currentInstance = instances.stream()
.filter(p -> p.i == i)
.findFirst()
.get(); // you can use get if you are sure there's one instance
The predicate p -> p.i == i seems suspicious. Why not using equals() instead?
As described, this would normally be solved with streams in the following way:
Optional<Instance> first =
instances.stream().filter(p -> p.i == i).findFirst();
(of which there should be only one)
Of which there definitely is only one, or of which there might be more than one. (And if there's more than one, then what? Is that an error?) It sounds like it might be that you should have a Set<Instance>, not a List<Instance>. Just an observation.
You can do it like
instances.forEach(p -> {
if (p.i == i) n.add(p);
});

Alternative to returning null value

I think is a bad idea to return null values so I am looking to an alternative to this.
Here is my code:
public Flight getFlight(String id) {
for (Flight f : this.flightList ) {
if ( f.getId().equals(id))
return f;
}
return null;
}
I am looking for a certain Flight with a certain id and I want to return it.
If I return null I have to check every time if the object I returned is null or not. And I would like to avoid this if possible.
So any suggestions are welcome.
This really depends if the event "a flight was not found" is considered exceptional or not.
When you call this method, if the calling code expects a valid flight all the time then not finding it is exceptional. There should be a flight but there isn't one. In this scenario, it is best to throw a custom Exception like FlightNotFoundException, that contains the id of the searched flight. It would typically be a RuntimeException: the flight should have been there, there is nothing you can do to recover from this.
However, if this requirement is not met, I don't see anything wrong with returning null, as long as this is correctly documented.
You can take a look at Null object pattern (in C# is implemented as string.Empty), since it
replaces check of NULL object instance. Instead of putting if check for a null value, Null Object reflects a do nothing relationship. Such Null object can also be used to provide default behaviour in case data is not available.
In your case it could be something like:
public class NullFlight extends AbstractFlight {
#Override
public String getId() {
return "Not Available for null Flight!";
}
#Override
public boolean isNil() {
return true;
}
}
Also this is a valid case when dealing with collections, you should return 'new' empty ones instead of Null.
Generally returning null instead of an object is a bad practice. There are two alternatives to returning null.
Fistly I would recommend to check out Null Object Pattern with defined neutral ("null") behavior.
The second idea is to thrown your own Exception when you can't return an object.
if ( f.getId().equals(id)){
return f;
}else throw new FlightNotFoundException();

ConcurrentHashMap Conditional Replace

I'd like to be able to conditionally replace a value in a ConcurrentHashMap. That is, given:
public class PriceTick {
final String instrumentId;
...
final long timestamp;
...
And a class (let's call it TickHolder) which owns a ConcurrentHashMap (let's just call it map).
I wish to be able to implement a conditional put method, so that if there's no entry for the key, the new one is inserted, but if there is an existing entry, the new one is inserted only if the timestamp value in the new PriceTick is greater than the existing one.
For an old-school HashMap solution, TickHolder would have a put method:
public void add(PriceTick tick) {
synchronized(map) {
if ((map.get(tick.instrumentId) == null)
|| (tick.getTimestamp() > map.get(tick.instrumentId).getTimestamp()) )
map.put(tick.instrumentId, tick);
}
}
With a ConcurrentHashMap, one would want to drop the synchronization and use some atomic method like replace, but that's unconditional. So clearly the "conditional replace" method must be written.
However, since the test-and-replace operation is non-atomic, in order to be thread safe, it would have to be synchronized - but my initial reading of the ConcurrentHashMap source leads me to think that external synchronization and their internal locks will not work very well, so at a very minimum, every Map method which performs structural changes and the containing class performs would have to be synchronized by the containing class... and even then, I'm going to be fairly uneasy.
I thought about subclassing ConcurrentHashMap, but that seems to be impossible. It makes use of an inner final class HashEntry with default access, so although ConcurrentHashMap is not final, it's not extensible.
Which seems to mean that I have to fall back to implementing TickHolder as containing an old-school HashMap in order to write my conditional replace method.
So, the questions: am I right about the above? Have I (hopefully) missed something, whether obvious or subtle, which would lead to a different conclusion? I'd really like to be able to make use of that lovely striped locking mechanism here.
The non-deterministic solution is to loop replace():
do {
PriceTick oldTick = map.get(newTick.getInstrumentId());
} while ((oldTick == null || oldTick.before(newTick)) && !map.replace(newTick.getInstrumentId(), oldTick, newTick);
Odd though it may seem, that is a commonly suggested pattern for this kind of thing.
#cletus solution formed the base for my solution to an almost identical problem. I think a couple of changes are needed though as if oldTick is null then replace throws a NullPointerException as stated by #hotzen
PriceTick oldTick;
do {
oldTick = map.putIfAbsent(newTick.getInstrumentId());
} while (oldTick != null && oldTick.before(newTick) && !map.replace(newTick.getInstrumentId(), oldTick, newTick);
The correct answer should be
PriceTick oldTick;
do {
oldTick = map.putIfAbsent(newTick.getInstrumentId(), newTick);
if (oldTick == null) {
break;
}
} while (oldTick.before(newTick) && !map.replace(newTick.getInstrumentId(), oldTick, newTick);
As an alternative, could you create a TickHolder class, and use that as the value in your map? It makes the map slightly more cumbersome to use (getting a value is now map.getValue(key).getTick()), but it lets you keep the ConcurrentHashMap's behavior.
public class TickHolder {
public PriceTick getTick() { /* returns current value */
public synchronized PriceTick replaceIfNewer (PriceTick pCandidate) { /* does your check */ }
}
And your put method becomes something like:
public void updateTick (PriceTick pTick) {
TickHolder value = map.getValue(pTick.getInstrumentId());
if (value != null) {
TickHolder newTick = new TickHolder(pTick);
value = map.putIfAbsent(pTick.getInstrumentId(), newTick);
if (value == null) {
value = newTick;
}
}
value.replaceIfNewer(pTick);
}

Categories