//How can we handle the below code in functional way like collect all invalid sort params, prepare message with all them listed and finally throw InvalidSortParam exception.
DO you think the below query does it?
public Sort resolveArgument() {
Sort sort = sortHandlerMethodArgumentResolver.resolveArgument();
List<Sort.Order> orders = sort.stream().collect(Collectors.toList());
List<String> invalidSortList = orders.stream().map(Sort.Order::getProperty)
.filter(property -> !allowedSortParams.contains(property))
.collect(Collectors.toList());
if (orders.isEmpty()) {
sort = Sort.by(Sort.Direction.DESC, defaultSortParam);
} else {
if (orders.size() > sortMaxCount) {
throw new InvalidSortException(INVALID_SIZE_PARAMS);
} else {
if (!invalidSortList.isEmpty()) {
throw new InvalidSortException(invalidSortList.stream()
.collect(Collectors.joining(",")) + INVALID_SORT_PARAMS);
}
}
}
return sort;
}
First of all - you do not take advantage of the streaming functionality, you divided it into two separate steps - loading data, and when it is completed - transforming it. You could merge it into a single pipeline. Secondly - throwing exceptions is not a functional way. You should use some type to return a state e.g with some Try implementation.
final class Try<T> {
private final Exception e;
private final T t;
public Try(Exception e) {
this.e = e;
t = null;
}
public Try(T t) {
this.t = t;
e = null;
}
public Exception getE() {
return e;
}
public T getT() {
return t;
}
}
and the code itself could look something like
public Try<Sort> resolveArgument() {
int cnt = getCount();
return cnt == 0 ? Sort.by(Sort.Direction.DESC, defaultSortParam) : someErrorHandlingLogic(cnt);
}
private static void getCount() {
sort.stream().map(Sort.Order::getProperty)
.filter(property -> !allowedSortParams.contains(property))
.count();
}
If you're interested in the Functional Programming paradigm in java - I recommend great presentation https://dev.tube/video/YnzisJh-ZNI
Related
My Idea shows that I have common code for two classes and I should make it one due to DRY rule (Don't Repeat Yourself).
class LongPersistence {
public void storeSomeNiceNumber(#NotNull Long l) {
if (l < 0) {
throw new RuntimeException("value should not be negative");
}
someNicePersistence.store(new String(l).getBytes());
}
}
public Long retrieveSomeNiceNumber() {
try {
byte[] bytesRepr someNicePersistence.retrieve();
Long value = Long.parseLong(new String(bytesRepr));
return value;
} catch (SomeNicePersistenceException e) {
return 0L;
}
}
}
So i started working...
class Persistence<N extends Number> {
... and failed as:
Number cannot be compared to 0.
I cannot return 0 to a Number.
I think this should be possible in well-defined langue, as Java I had been considering so far. Am I missing something? Please advise how to make this algorithm common to Long and Integer (and as an A+ task for any Number)
Thanks to #VGR I understood that I required math logic from java.lang.Number class which is intended to store numbers as Objects only (something like a Variant type), therefore I have externalized the math to another interface, which in my opinion makes more sense.
public interface NumberMath<E extends Number> {
E parse(String string);
String toString(E e);
E zero();
int signum(E e);
}
class NumberPersistence<E extends Number> {
private final NumberMath<E> math;
private final SomeNicePersistence someNicePersistence;
public NumberPersistence(NumberMath<E> math, SomeNicePersistence persistence) {
this.someNicePersistence = persistence;
this.math = math;
}
public void storeSomeNiceNumber(E l) {
if (math.signum(l) < 0) {
throw new RuntimeException("value should not be negative");
}
someNicePersistence.store(math.toString(l).getBytes());
}
public E retrieveSomeNiceNumber() {
try {
byte[] bytesRepr = someNicePersistence.retrieve();
E value = math.parse(new String(bytesRepr));
return value;
} catch (SomeNicePersistenceException e) {
return math.zero();
}
}
}
I have bounded the E to Number, but to be honest, in this case it is not required anymore.
i have the code like this when i create it like this
public final class PhpArray extends AbstractMap
{
private TreeMap t;
private HashMap m;
public PhpArray() {
this.t = new TreeMap(Request.PHP_ARRAY_KEY_COMPARATOR);
this.m = null;
}
#Override
public Object put(final Object key, final Object value) {
if (this.m != null) {
return this.m.put(key, value);
}
try {
return this.t.put(key, value);
}
catch (ClassCastException e) {
this.m = new HashMap(this.t);
this.t = null;
return this.m.put(key, value);
}
}
#Override
public Set entrySet() {
if (this.t != null) {
return this.t.entrySet();
}
return this.m.entrySet();
}
public int arraySize() {
if (this.t == null) {
throw new IllegalArgumentException("The passed PHP \"array\" is not a sequence but a dictionary");
}
if (this.t.size() == 0) {
return 0;
}
return 1 + this.t.lastKey();
}
}
but when i update my project i got error in the code
return 1 + this.t.lastKey();
the error is an arguments + is undefined.. why like that ? and how to fix the problem ?
TreeMap is a generic class but in the code in your question you have used it without type parameters. This means that this line of your code:
private TreeMap t;
is essentially this:
private TreeMap<Object, Object> t;
In other words t.lastKey() returns an Object and the operator + can't be used with Object because an Object is not a number.
Perhaps you meant to call method size() rather than method lastKey()?
Perhaps this tutorial will help?
Imagine I have, say, XML-generated entity in Java that holds some data I need.
For example:
<Car>
<Engine>
<Power>
175
</Power>
</Engine>
</Car>
So if I need an engine power, I, followed by the best practices of business software development, will do the next thing:
Car car = dao.getCar()
Power power = car != null && car.engine != null ? power : null
return power
I hate this. Sometimes it seems that half of the code is just null checks.
Any ideas?
Take a look at Java 8 Optional class.
It does exactly that: it avoids the ugly checks on null.
In your case, you could use this snippet of code to avoid them:
Car car = dao.getCar();
Optional<Car> optionalCar = Optional.ofNullable(car);
Optional<Power> optionalPower = getPowerIfPresent(optionalCar);
Power power = Optional.empty();
if(optionalPower.isPresent()) {
power = optionalPower.get();
}
after writing a function that returns the power of a given car:
public static Optional<Power> getPowerIfPresent(Optional<Car> car) {
return car
.flatMap(c -> c.getEngine())
.map(e -> e.getPower());
}
This is the same as using of Optional, but might be more readable:
public class NullSafe<T> {
private final T value;
public NullSafe(#Nullable T value) { this.value = value; }
public static <T> NullSafe<T> of(#Nullable T value) { return new NullSafe<>(value); }
public <R> NullSafe<R> get(Function<T,R> mapper) {
R newValue = (value != null) ? mapper.apply(value) : null;
return new NullSafe<>(newValue);
}
public T nullable() { return value; }
public T orDefault(T defaultValue) { return (value != null) ? value : defaultValue; }
}
And usage:
Power power = NullSafe.of(dao.getCar())
.get(Car::getEngine)
.get(Engine::getPower)
.nullable(); // .orDefault(Power.defaultPower());
An alternative can be static methods:
public static <R> R get(Supplier<R> supplier, R defaultValue) {
try { return supplier.get(); }
catch (NullPointerException ex) { return defaultValue; }
}
public static <R> R getNullable(Supplier<R> supplier) { return get(supplier, null); }
And usage:
Power power = NullSafe.get(() -> dao.getCar().getEngine().getPower(), Power.defaultPower());
Power powerOrNull = NullSafe.getNullable(() -> dao.getCar().getEngine().getPower());
My own approach kind of this now:
public class CarDataExtractor {
private final Car car;
private CarDataExtractor(Car car) {
this.car = car;
}
public static CarDataExtractor on(Car car) {
return new CarDataExtractor(car);
}
public EngineDataExtractor engine() {
return car != null && car.getEngine() != null
? EngineDataExtractor.on(car.getEngine())
: EngineDataExtractor.on(null);
}
public Car self() {
return car;
}
}
public class EngineDataExtractor {
private final Engine engine;
private EngineDataExtractor(Engine engine) {
this.engine = engine;
}
public static EngineDataExtractor on(Engine engine) {
return new EngineDataExtractor(engine);
}
public PowerDataExtractor engine() {
return engine != null && engine.getPower() != null
? PowerDataExtractor.on(engine.getPower())
: PowerDataExtractor.on(null);
}
public Engine self() {
return engine;
}
}
...
Power power = CarDataExtractor.on(dao.getCar()).engine().power().self()
It is because I am restricted to Java 6...
Or maybe create some util method:
static <T> Optional<T> tryGet(Supplier<T> getter) {
try {
return Optional.ofNullable(getter.get());
} catch(NullPointerException ignored) {
return Optional.empty();
}
}
Then you could use it like this:
System.out.println(tryGet(() -> car.engine.power).orElse(new Power()));
There is a library no-exception that does that, but you cannot specify it to only "silence" NPEs.
Exceptions.silence().get(() -> car.engine.power).orElse(new Power())
There is also another option, you could use, which might be helpful for you if you're using Spring.
If you're not using Spring you would need to add additional dependency to your project.
Using Spel you could do:
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext(dao.getCar());
Power power = parser.parseExpression("engine?.power").getValue(context, Power.class);
In expression engine?.power safe navigation operator is being used. In case engine is null, then the whole expression will evaluate to null.
This solution will work on Java 6.
Sometimes methods have the only difference somwhere in the middles of their bodies and it's difficult to generalize them or extract common part of code to a single method.
Question itself: How would you refactor the following implementations of interface methods to avoid duplicate code around for loop body?
interface MyInterface {
Integer myInterfaceMethod(String inputStr);
Integer myInterfaceOtherMethod(String inputStr)
}
class MyClass implements MyInterface {
public Integer myInterfaceMethod(String inputStr) {
#Override
try {
List<String> listDependingOnString = getListByString(inputStr);
Integer result = -1;
if (inputStr != null) {
result = 0;
for (String str : listDependingOnString) {
// Some different code, given just for example
result += str.length();
}
}
return result;
} catch (Exception e) {
exceptionProcessing(e);
return null;
}
}
#Override
public Integer myInterfaceOtherMethod(String inputStr) {
try {
List<String> listDependingOnString = getListByString(inputStr);
Integer result = -1;
if (inputStr != null) {
result = 0;
for (String str : listDependingOnString) {
// Some different code, given just for example
System.out.println(str);
++result;
}
}
return result;
} catch (Exception e) {
exceptionProcessing(e);
return null;
}
}
}
For this particular example, a lambda would work nicely:
private Integer computeStringFunction(String inputStr, BiFunction<Integer,String,Integer> accumulator) {
try {
List<String> listDependingOnString = getListByString(inputStr);
Integer result = -1;
if (inputStr != null) {
result = 0;
for (String str : listDependingOnString) {
result = accumulator.apply(result, str);
}
}
return result;
} catch (Exception e) {
exceptionProcessing(e);
return null;
}
public Integer myInterfaceMethod(String inputStr) {
return computeStringFunction(inputStr,
(Integer oldValue, String str) -> oldValue + str.length());
}
public Integer myInterfaceOtherMethod(String inputStr) {
return computeStringFunction(inputStr,
(Integer oldValue, String str) -> {
System.out.println(str);
return oldValue + 1;
});
}
"accumulator" here is a function that takes an integer and a string and returns another integer, and whose intent is to keep a "running total" of some sort.
BiFunction documentation
Note: not tested
The key to remove duplicate pattern in codes is to abstract the common part to one place and then find a way to pass the different part of "code pieces" as parameters to execute, for languages in which function is first class citizen(JavaScript, Python), you can always wrap the "code pieces" as functions. But it's not applicable for Java because method in Java is not a value, one way to resolve it is to define interfaces, and then pass the instance of a class which implements the interface as parameters, with lambda expression in Java 8 it can be more simpler.
Take the code in question as example, the common pattern is:
iterate the list and process each item
accumulate the result of each item and return
Then we can define two interfaces:
#FunctionalInterface
public interface ItemHandler<T, R> {
/**
* Takes input item of type T, then returns result of type R
*/
R handle(T t);
}
And another interface to accumulate the result:
#FunctionalInterface
public interface ItemResultAccumulator<T> {
T accumulate(T t1, T t2);
}
and then your code could be refactored as(I removed all exception handling and null checking code, to make the code less verbose to view):
public class MyClass implements MyInterface {
private static final ItemResultAccumulator<Integer> ADDER = (t1, t2) -> t1 + t2;
#Override
public Integer myInterfaceMethod(String inputStr) {
return processList(getListByString(inputStr), s -> s.length(), ADDER);
}
#Override
public Integer myInterfaceOtherMethod(String inputStr) {
return processList(getListByString(inputStr), s -> {
System.out.println(s);
return Integer.valueOf(1);
}, ADDER);
}
private Integer processList(List<String> list, ItemHandler<String, Integer> handler, ItemResultAccumulator<Integer> accumulator) {
Integer result = 0;
if (list != null && list.size() > 0) {
for (String item : list) {
result = accumulator.accumulate(result, handler.handle(item));
}
}
return result;
}
private List<String> getListByString(String inputStr) {
// Your logic to generate list by input
return Lists.newArrayList(inputStr.split(","));
}
}
This is a little of my thinking of this problem, hope this could be helpful:-)
I am trying to make use of Java 8 and streams and one of the things I am trying to replace is a system we have where we
Use an aspect to measure call latency (per config period of time) to out webservices and then
Feed those results into a Complex Event Processor (esper) so that
We can send out alert notifications
So, one step at a time. For the first step, I need to produce a stream (I think) that allows me to feed those latency numbers into existing listeners. Understanding that, getting the next number in series might have to wait until there is a call.
How can I do that? Here is the latency aspect with comments.
public class ProfilingAspect {
private ProfilingAction action;
public ProfilingAspect(ProfilingAction action) {
this.action = action;
}
public Object doAroundAdvice(ProceedingJoinPoint jp) throws Throwable{
long startTime = System.currentTimeMillis();
Object retVal = null;
Throwable error = null;
try{
retVal = jp.proceed();
}catch (Throwable t){
error = t;
}
Class withinType = jp.getSourceLocation().getWithinType();
String methodName = jp.getSignature().getName();
long endTime = System.currentTimeMillis();
long runningTime = endTime - startTime;
// Let the IntStream know we have a new latency. Or really, we have an object
// stream with all this extra data
action.perform(withinType, methodName, jp.getArgs(), runningTime, error);
if( error != null ){
throw error;
}
return retVal;
}
}
Ok, I have a working example. It doesn't handle the situation where I have to buffer up results though is the stream isn't being read fast enough. I am open to some improvement
public class LatencySupplier implements Supplier<SomeFancyObject> {
private Random r = new Random();
#Override
public SomeFancyObject get() {
try {
Thread.sleep(100 + r.nextInt(1000));
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return new SomeFancyObject(10 + r.nextInt(1000));
}
}
public class SomeFancyObject {
private static String[] someGroups = {"Group1","Group2","Group3"};
private final String group;
private int value;
public SomeFancyObject(int value) {
this.value = value;
this.group = WSRandom.selectOne(someGroups);
}
public String getGroup() {
return group;
}
public int getValue() {
return value;
}
#Override
public String toString() {
return value + "";
}
}
My next step is to create a stream by time so I can do avg/5 min, etc.
public class Sample {
public static void main(String[] args) throws InterruptedException {
Stream<SomeFancyObject> latencyStream = Stream.generate(new LatencySupplier());
Map<Object,List<SomeFancyObject>> collect = latencyStream.limit(10).collect(Collectors.groupingBy(sfo -> sfo.getGroup()));
System.out.println(collect);
Object o = new Object();
synchronized (o){
o.wait();
}
}
}