Mapping a Nested Optional? - java

I'm kind of running into a tedious issue with the Java 8 "Optional" container. I cannot map an Optional to "bubble up" another optional.
Let's say I have a RussianNestingDoll class
public class NestedOptionalTest {
public static void main(String[] args) {
RussianNestingDoll doll = RussianNestingDoll.createInstance(RussianNestingDoll.createInstance(RussianNestingDoll.createInstance()));
Optional<Optional<RussianNestingDoll>> thirdDollContents = doll.getInnerDoll().map(d -> d.getInnerDoll());
if (thirdDollContents.isPresent() && thirdDollContents.get().isPresent()) {
System.out.println(thirdDollContents.get().get());
}
else {
System.out.println("empty");
}
}
private static final class RussianNestingDoll {
private final Optional<RussianNestingDoll> innerDoll;
public Optional<RussianNestingDoll> getInnerDoll() {
return innerDoll;
}
private RussianNestingDoll(Optional<RussianNestingDoll> innerDoll) {
this.innerDoll = innerDoll;
}
public static RussianNestingDoll createInstance() {
return new RussianNestingDoll(Optional.empty());
}
public static RussianNestingDoll createInstance(RussianNestingDoll innerDoll) {
return new RussianNestingDoll(Optional.of(innerDoll));
}
}
}
It would be nice to not have to use nested optionals, and instead just have the optional "bubble up". That way I can call "isPresent()" and "get()" just once, rather than calling them both twice. Is there a way I can accomplish this?

I'm not really sure what you want, but you can rewrite your code like this:
RussianNestingDoll doll = RussianNestingDoll.get(RussianNestingDoll.get(RussianNestingDoll.get()));
String content = doll.getInnerDoll()
.flatMap(d -> d.getInnerDoll())
.map(d -> d.get().toString())
.orElse("empty");
System.out.println(content);
In case you want to use the doll afterwards:
Optional<RussianNestingDoll> thirdDoll = doll.getInnerDoll()
.flatMap(d -> d.getInnerDoll());
if (thirdDoll.isPresent()) {
System.out.println(thirdDoll.get());
}
else {
System.out.println("empty");
}

Do you want to flatMap?
thirdDollContents
.flatMap(Function.identity()) // un-nest, get back an Optional<RussianNestingDoll>
.get() // or isPresent()
The flatMap will return an empty Optional if thirdDollContents is empty.

Related

How do I cleanly drill down through nested object in Java?

I have the following Java class:
public class MyClass{
private List<Settings> settings;
public static class Settings {
private String name;
private List<Features> features;
}
public static class Features {
private String name;
private Boolean isActive;
}
}
What I want to do is first check that settings is not null or empty. If not, then I want to find the Settings object that has the name "reliability", and then find its Features objects that have the names "logs" and "score" and get the isActive from these two objects.
This is what I've tried:
MyClass myClass = new MyClass ();
Boolean logs = false;
Boolean score = false;
if (myClass.getSettings != null) {
for (Settings setting: myClass.getSettings) {
if (setting.getName().equals("reliability")) {
for (Features features : setting.getFeatures) {
if (features.getName().equals("logs")) {
logs = features.getIsActive;
} else if (features.getName().equals("score")) {
score = features.getIsActive;
}
}
}
}
}
How do I do this in a clean way? I can only do it with countless nested if and for loops, and it is not pretty.
Here is the possible solution with Streams.
I assume that there would be no duplicated Features (i.e. having the same name) objects.
By the way, class names are usually singular nouns. Class Features is meant to represent a single object with a distinct name and a single property isActive. Therefore, the name Feature might` be more suitable.
The method below expects an argument of type MyClass, settings name and varargs of names of target features. The result it produces is Map with feature names as keys and corresponding isActive properties as values.
public static Map<String, Boolean> getFeaturesByName(MyClass myClass,
String settingName,
String... featureNames) {
if (myClass.getSettings() == null) return Collections.emptyMap();
Set<String> featureSet = Set.of(featureNames);
return myClass.getSettings().stream()
.filter(settings -> settings.getName().equals(settingName))
.flatMap(settings -> settings.getFeatures().stream())
.filter(features -> featureSet.contains(features.getName()))
.collect(Collectors.toMap(
MyClass.Features::getName,
MyClass.Features::getActive
));
}
Delegate the "drilling" to your classes:
add to MyClass
public boolean hasSettings() {
return settings != null && !settings.isEmpty();
}
public Settings getSetting(String name) {
return settings.stream()
.filter(s -> s.hasName(name))
.findFirst()
.orElseThrow(() -> new IllegalStateException("No settings with name " + name));
}
add to Settings
public boolean hasName(String name) {
return this.name.equals(name);
}
public Features getFeature(String name) {
return features.stream()
.filter(f -> f.hasName(name))
.findFirst()
.orElseThrow(() -> new IllegalStateException("No feature with name " + name));
}
add to Features
public boolean hasName(String name) {
return this.name.equals(name);
}
Then you can do
if (myClass.hasSettings()) {
Settings reliabilitySetting = myClass.getSetting("reliability");
logs = reliabilitySetting.getFeature("logs").isActive();
score = reliabilitySetting.getFeature("score").isActive();
}
NOTE: You can return Optionals if you don't want to throw exceptions.
Well to check if the object is nullable or not you can use the optional class then regarding of find the setting object you have an option to use Java Stream Filter to filter the result.
You can stream API to reduce the code
private static final String SETTINGS_NAME_FOR_CHECK = "reliability";
private static final List<String> FEATURES_NAME_FOR_CHECK = Arrays.asList("logs", "score");
public static void main(String[] args) {
MyClass myClass = new MyClass();
if(myClass.getSettings() != null) {
Settings correctSettings = myClass.getSettings().stream()
.filter(setting -> SETTINGS_NAME_FOR_CHECK.equals(setting.getName()))
.findFirst().orElse(null);
if(correctSettings.getFeatures() != null) {
List<Features> features = correctSettings.getFeatures().stream()
.filter(feature -> (FEATURES_NAME_FOR_CHECK.contains(feature.getName()))).collect(Collectors.toList());
System.out.println(features);
}
}
}
Once you get the features (which will be only having logs and shares), you can check for the boolean value.
To make your code cleaner you can move logic into support methods. This also makes it more testable. In your code you are inspecting an instance of MyClass to determine if it certain features which are identified by name. You could write a method that does just that. Your original code could be re-written as:
MyClass myClass = ...
boolean hasLogs = hasSettingFeature(myClass, "reliability", "logs");
boolean hasScore = hasSettingFeature(myClass, "reliability", "score");
You can iterate through the given instance within the support model. You can do with this for-loops.
public boolean hasSettingFeature(MyClass myClass, String settingName, String featureName) {
if (null == myClass || null == myClass.getSettings()) {
return false;
}
for (Settings settings : myClass.getSettings()) {
if (settingName.equals(settings.getName()) {
for (Features features : settings.getFeatures()) {
if (featureName.equals(features.getName()) {
return true;
}
}
}
}
return false;
}
You may also use the Stream API to filter to determine the state:
public boolean hasSettingFeature(MyClass myClass, String settingName, String featureName) {
if (null == myClass || null == myClass.getSettings()) {
return false;
}
return myClass.getSettings().stream()
.filter(setting -> settingName.equals(setting.getName()))
.flatMap(setting -> setting.getFeatures())
.filter(features -> featureName.equals(features.getName()))
.findAny()
.isPresent();
}
I think, a more fitting datastructure would be the Map. I presume every Features exists only once?
public class MyClass {
private Map<String, Settings> settings;
public static class Settings {
private String name;
private Map<String, Features> features;
}
public static class Features {
private String name;
private Boolean isActive;
}
public static void main(String[] args) {
MyClass t = new MyClass();
Boolean logs = null, score = null;
Settings s = t.settings.get("reliability");
if (s != null) {
Features f;
if ((f = s.features.get("logs")) != null) // Is "features" null-save?
logs = f.isActive;
else if ((f = s.features.get("score")) != null)
score = f.isActive;
}
System.out.println("Logs: " + logs + ", Score: " + score);
}
}
(Also it is very bad practice to use the nullable wrapperclass Boolean. You might wanna do something about that.)
If you have problems turning your existing lists into maps, use this method:
public static void main(String[] args) {
Map<String, Settings> map = toMap(List.of(new Settings()), s -> s.name);
}
static <K, V> Map<K, V> toMap(Collection<V> c, Function<V, K> func) {
return c.stream().collect(Collectors.toMap(func, v -> v));
}

function name as a string

I am trying to wrap my head around generic and functions... what I am trying to achieve: Passing function name as a string to get it executed:
I want to do Wrapper.useFunction("eleven") or Wrapper.useFunction("ten")
public class Wrapper<T> {
public F useFunction(Function<F, F> function) {
return function.apply(F);
}
Function<F, String> ten = s -> "10";
Function<F, String> eleven = s -> "11";
}
But this code not even close to compiling. Maybe it doesn't make any sense. Any suggestions?
If you have a finite set of functions which you would like to be able to call I would recommend building a Map which maps Strings to instances of Runnable (or similar functional interfaces). Your useFunction method may then look up the function implementation in the Map and call it if it exists.
Example:
public class SomeClass {
private final Map<String, Runnable> methods = new HashMap<>();
{
methods.put("helloworld", () -> {
System.out.println("Hello World!");
});
methods.put("test", () -> {
System.out.println("test!");
});
methods.put("doStuff", () -> {
System.out.println("doStuff!");
});
}
public void perform(String code) {
methods.getOrDefault(code,
() -> {
System.err.println("No such Method: "+code);
})
.run();
}
}
If you want to call arbitrary methods you should probably use Reflection as stated by others.

How can I intercept an observable object and modify it in RxJava before returning to Subscriber?

I'm currently trying to hit a service and get returned a list of objects, before it gets returned to the subscriber, I want to make another synchronous call for each object in the list to make another service call to set a missing field. I'm successfully having all calls being made, but the object returned in the subscriber has this field I need to have set to null. Here is an example of my code:
Example Service:
rx.Observable<List<ExampleObject>> getExampleObject();
rx.Observable<MissingObject> getMissingObjectByFoo(#Path("foo") String foo);
Example Class:
public class ExampleObject {
String foo;
MissingObject bar;
public String getFoo() {
return this.foo;
}
public void setFoo(String value) {
this.foo = value;
}
public MissingObject getBar() {
return this.bar;
}
public void setBar(MissingObject value) {
this.bar = value;
}
}
Example Implementation:
mService.getExampleObject().flatMap(new Func1<List<ExampleObject>, Observable<?>>() {
#Override
public Observable<List<ExampleObject>> call(List<ExampleObject> exampleObjects) {
for (ExampleObject entry : exampleObjects) {
String foo = entry.getFoo();
mService.getMissingObjectByFoo(foo)
.subscribeOn(mScheduler.backgroundThread())
.observeOn(mScheduler.mainThread())
.subscribe(new Subscriber<MissingObject>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(MissingObject missingObject) {
entry.setBar(missingObject);
}
});
}
return Observable.just(exampleObjects);
};
Because your intermediary call to update the entry is asynchronous, I don't think you can stick to using a List<ExampleObject>, but should instead manipulate ExampleObject directly from the Observable:
mService.getExampleObject()
// Spread the list
.flatMap(list -> Observable.from(list))
// Update your object
// Here we zip the object with the missing object,
// so that when the missing object is obtained,
// we update the entry and emit it.
.flatMap(entry -> Observable.zip(
Observable.just(entry),
mDocsService.getMissingObjectByFoo(entry.getFoo()),
(entry, missingObject) -> {
entry.setBar(missingObject);
return entry;
})
)
// if you really want a map after all
.toList();
Side note:
You can skip the zip if you are fine with having the function in the map depend on an external variable (the entry). That's something I try to avoid, but here it is anyway:
.flatMap(entry -> mDocsService.getMissingObjectByFoo(entry.getFoo())
.map(missingObject -> {
entry.setBar(missingObject);
return entry;
})
)
You're looking for the zip operator, as described here: Zip Operator. I think you want to flatmap to a zip of all of your calls, so, something like this:
mService.getExampleObject().flatMap(new Func1<List<ExampleObject>, Observable<ExampleObject>>() {
#Override
public Observable<List<ExampleObject>> call(List<ExampleObject> exampleObjects) {
List<Observable<ExampleObject>> allTheObservables = new ArrayList<Observable<ExampleObject>>();
for (ExampleObject entry : exampleObjects) {
allTheObservables.add(mService.getMissingObjectByFoo(foo).map(new Func1<MissingObject, ExampleObject>() {
#Override
public ExampleObject call(MissingObject missingObject) {
return entry.setBar(missingObject);
}
}));
}
return Observable.zip(allTheObservables, new FuncN<ExampleObject>() {
#Override
public ExampleObject call(ExampleObject... args) {
return Arrays.asList(args);
}
});
}
});
and in case that doesn't work, or there are syntax issues, here's a concrete example, using the github api:
service.getContributorsObservable("square", "dagger")
.flatMap(new Func1<List<Contributor>, Observable<List<String>>>() {
#Override
public Observable<List<String>> call(List<Contributor> contributors) {
List<Observable<String>> allTheObservables = new ArrayList<>(contributors.size());
for (final Contributor contributor : contributors) {
allTheObservables.add(service.getContributorsObservable(contributor.login).map(new Func1<User, String>() {
#Override
public String call(User user) {
return contributor.login + " is " + user.name;
}
}));
}
return Observable.zip(allTheObservables, new FuncN<List<String>>() {
#Override
public List<String> call(Object... args) {
return Arrays.asList((String[]) args);
}
});
}
});
Keep in mind that this will make n+1 network calls, 1 for the list of ExampleObjects, and then 1 per ExampleObject in that list. If it is at all possible, I strongly suggest that you speak with the maintainer of the API to get the information lookup taken care of on the API side. Just know that this is going to use some bandwidth!

Java Optionals - how to write in functional style? [duplicate]

I want to replace the following code using java8 Optional:
public Obj getObjectFromDB() {
Obj obj = dao.find();
if (obj != null) {
obj.setAvailable(true);
} else {
logger.fatal("Object not available");
}
return obj;
}
The following pseudocode does not work as there is no orElseRun method, but anyways it illustrates my purpose:
public Optional<Obj> getObjectFromDB() {
Optional<Obj> obj = dao.find();
return obj.ifPresent(obj.setAvailable(true)).orElseRun(logger.fatal("Object not available"));
}
With Java 9 or higher, ifPresentOrElse is most likely what you want:
Optional<> opt = dao.find();
opt.ifPresentOrElse(obj -> obj.setAvailable(true),
() -> logger.error("…"));
Currying using vavr or alike might get even neater code, but I haven't tried yet.
I don't think you can do it in a single statement. Better do:
if (!obj.isPresent()) {
logger.fatal(...);
} else {
obj.get().setAvailable(true);
}
return obj;
For Java 8 Spring Data offers ifPresentOrElse from "Utility methods to work with Optionals" to achieve what you want.
Example would be:
import static org.springframework.data.util.Optionals.ifPresentOrElse;
ifPresentOrElse(dao.find(), obj -> obj.setAvailable(true), () -> logger.fatal("Object not available"));
You will have to split this into multiple statements. Here is one way to do that:
if (!obj.isPresent()) {
logger.fatal("Object not available");
}
obj.ifPresent(o -> o.setAvailable(true));
return obj;
Another way (possibly over-engineered) is to use map:
if (!obj.isPresent()) {
logger.fatal("Object not available");
}
return obj.map(o -> {o.setAvailable(true); return o;});
If obj.setAvailable conveniently returns obj, then you can simply the second example to:
if (!obj.isPresent()) {
logger.fatal("Object not available");
}
return obj.map(o -> o.setAvailable(true));
There is an .orElseRun method, but it is called .orElseGet.
The main problem with your pseudocode is that .isPresent doesn't return an Optional<>. But .map returns an Optional<> which has the orElseGet method.
If you really want to do this in one statement this is possible:
public Optional<Obj> getObjectFromDB() {
return dao.find()
.map( obj -> {
obj.setAvailable(true);
return Optional.of(obj);
})
.orElseGet( () -> {
logger.fatal("Object not available");
return Optional.empty();
});
}
But this is even clunkier than what you had before.
First of all, your dao.find() should either return an Optional<Obj> or you will have to create one.
e.g.
Optional<Obj> = dao.find();
or you can do it yourself like:
Optional<Obj> = Optional.ofNullable(dao.find());
this one will return Optional<Obj> if present or Optional.empty() if not present.
So now let's get to the solution,
public Obj getObjectFromDB() {
return Optional.ofNullable(dao.find()).flatMap(ob -> {
ob.setAvailable(true);
return Optional.of(ob);
}).orElseGet(() -> {
logger.fatal("Object not available");
return null;
});
}
This is the one liner you're looking for :)
For those of you who want to execute a side-effect only if an optional is absent
i.e. an equivalent of ifAbsent() or ifNotPresent() here is a slight modification to the great answers already provided.
myOptional.ifPresentOrElse(x -> {}, () -> {
// logic goes here
})
Title: "How to execute logic on Optional if not present?"
Answer:
Use orElseGet() as a workaround for the missing ifNotPresent(). And since it expects us to return something just return
null.
Optional.empty().orElseGet(() -> {
System.out.println("The object is not present");
return null;
});
//output: The object is not present
or
Optional.ofNullable(null).orElseGet(() -> {
System.out.println("The object is not present");
return null;
});
//output: The object is not present
I also use it to easily implement the singleton pattern with lazy initialization.
public class Settings {
private Settings(){}
private static Settings instance;
public static synchronized Settings getInstance(){
Optional.ofNullable(instance).orElseGet(() -> instance = new Settings());
return instance;
}
}
Of course the getInstance() content can be written in one line by directly returning the first statement, but I wanted to demonstrate the use of orElseGet() as an ifNotPresent().
I was able to came up with a couple of "one line" solutions, for example:
obj.map(o -> (Runnable) () -> o.setAvailable(true))
.orElse(() -> logger.fatal("Object not available"))
.run();
or
obj.map(o -> (Consumer<Object>) c -> o.setAvailable(true))
.orElse(o -> logger.fatal("Object not available"))
.accept(null);
or
obj.map(o -> (Supplier<Object>) () -> {
o.setAvailable(true);
return null;
}).orElse(() () -> {
logger.fatal("Object not available")
return null;
}).get();
It doesn't look very nice, something like orElseRun would be much better, but I think that option with Runnable is acceptable if you really want one line solution.
With Java 8 Optional it can be done with:
Optional<Obj> obj = dao.find();
obj.map(obj.setAvailable(true)).orElseGet(() -> {
logger.fatal("Object not available");
return null;
});
In order to get the value from one call, or do an extra call if the previous returned an empty value, you can chain the commands.
public Optional<Obj> getObjectFromDB() {
return dao.find().or(() -> dao.findBySomethingElse());
}
You need Optional.isPresent() and orElse(). Your snippet won;t work because it doesn't return anything if not present.
The point of Optional is to return it from the method.
ifPresentOrElse can handle cases of nullpointers as well. Easy approach.
Optional.ofNullable(null)
.ifPresentOrElse(name -> System.out.println("my name is "+ name),
()->System.out.println("no name or was a null pointer"));
I suppose you cannot change the dao.find() method to return an instance of Optional<Obj>, so you have to create the appropriate one yourself.
The following code should help you out. I've create the class OptionalAction,
which provides the if-else mechanism for you.
public class OptionalTest
{
public static Optional<DbObject> getObjectFromDb()
{
// doa.find()
DbObject v = find();
// create appropriate Optional
Optional<DbObject> object = Optional.ofNullable(v);
// #formatter:off
OptionalAction.
ifPresent(object)
.then(o -> o.setAvailable(true))
.elseDo(o -> System.out.println("Fatal! Object not available!"));
// #formatter:on
return object;
}
public static void main(String[] args)
{
Optional<DbObject> object = getObjectFromDb();
if (object.isPresent())
System.out.println(object.get());
else
System.out.println("There is no object!");
}
// find may return null
public static DbObject find()
{
return (Math.random() > 0.5) ? null : new DbObject();
}
static class DbObject
{
private boolean available = false;
public boolean isAvailable()
{
return available;
}
public void setAvailable(boolean available)
{
this.available = available;
}
#Override
public String toString()
{
return "DbObject [available=" + available + "]";
}
}
static class OptionalAction
{
public static <T> IfAction<T> ifPresent(Optional<T> optional)
{
return new IfAction<>(optional);
}
private static class IfAction<T>
{
private final Optional<T> optional;
public IfAction(Optional<T> optional)
{
this.optional = optional;
}
public ElseAction<T> then(Consumer<? super T> consumer)
{
if (optional.isPresent())
consumer.accept(optional.get());
return new ElseAction<>(optional);
}
}
private static class ElseAction<T>
{
private final Optional<T> optional;
public ElseAction(Optional<T> optional)
{
this.optional = optional;
}
public void elseDo(Consumer<? super T> consumer)
{
if (!optional.isPresent())
consumer.accept(null);
}
}
}
}

Looking for appropriate design pattern

Our code has several processors, each one having several api methods, where each method is overloaded also with same method that can accept collection.
For example:
public class Foo {
public X foo(Y y){...}
public Collection<X> foo(Collection<Y> y){... // iterate and execute foo(y) ... }
public Z bar(W w){...}
public Collection<Z> bar(Collection<W> w){... // iterate and execute bar(w) ... }
}
public class Other{
// also method and method on collection
}
Naturally, those methods on collections are actually duplication code of iteration.
What we are looking for, is kind of way to make some pattern or use generics, so the iteration over collection will be implemented once, also for that need a way to somehow pass the method name.
I'd suggest Startegy pattern. And do something like:
public interface Transformer<X, Y> {
Y transform( X input );
}
class Processor {
public <X,Y> Collection<Y> process( Collection<X> input, Transformer<X, Y> transformer) {
Collection<Y> ret = new LinkedList<Y>();
// generic loop, delegating transformation to specific transformer
for( X x : input) {
ret.add( transformer.transform( x ) );
}
return ret;
}
}
Example:
public static void main( String[] args ) {
List<String> strings = new LinkedList<String>();
strings.add( "1" );
strings.add( "2" );
strings.add( "3" );
Processor p = new Processor();
Collection<Integer> numbers = p.process( strings, new Transformer<String, Integer>() {
#Override
public Integer transform( String input ) {
return Integer.parseInt( input );
}
} );
}
I can't see how reflection could help here. You're trying to replace something as trivial as
public Collection<X> foo(Collection<Y> y) {
List<X> result = Lists.newArrayList();
for (Y e : y) result.add(foo(e));
return result;
}
by something probably much slower. I don't think that saving those 3 lines (several times) is worth it, but you might want to try either annotation processing (possibly without using annotations) or dynamic code generation. In both cases you'd write the original class as is without the collection methods and use a different one containing both the scalar and the collection methods.
Or you might want to make it more functionally styled:
public class Foo {
public final RichFunction<Y, X> foo = new RichFunction<Y, X>() {
X apply(Y y) {
return foo(y);
}
}
// after some refactoring the original method can be made private
// or inlined into the RichFunction
public X foo(Y y){...}
// instead of calling the original method like
// foo.foo(y)
// you'd use
// foo.foo.apply(y)
// which would work for both the scalar and collection methods
}
public abstract class RichFunction<K, V> extends com.google.common.base.Function<K, V> {
Collection<V> apply(Collection<K> keys) {
List<V> result = Lists.newArrayList();
for (K k : keys) result.add(apply(k));
return result;
}
}
RUAKH - I chosed to implement your suggestion for reflection (although, admit, I don't like reflection). So, I did something like the code below THANKS :)
public class Resource {
private static final int CLIENT_CODE_STACK_INDEX;
static {
// Finds out the index of "this code" in the returned stack trace - funny but it differs in JDK 1.5 and 1.6
int i = 0;
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
i++;
if (ste.getClassName().equals(Resource.class.getName())) {
break;
}
}
CLIENT_CODE_STACK_INDEX = i;
}
public static String getCurrentMethodName() {
return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX].getMethodName();
}
protected <IN,OUT> Collection<OUT> doMultiple(String methodName, Collection<IN> inCol, Class<?>... parameterTypes){
Collection<OUT> result = new ArrayList<OUT>();
try {
Method m = this.getClass().getDeclaredMethod(methodName, parameterTypes);
if (inCol==null || inCol.size()==0){
return result;
}
for (IN in : inCol){
Object o = m.invoke(this, in);
result.add((OUT) o);
}
}catch (Exception e){
e.printStackTrace();
}
return result;
}
}
public class FirstResource extends Resource{
public String doSomeThing(Integer i){
// LOTS OF LOGIC
return i.toString();
}
public Collection<String> doSomeThing(Collection<Integer> ints){
return doMultiple(getCurrentMethodName(), ints, Integer.class);
}
}
You should use Strategy pattern. By using Strategy pattern you can omit the usage if/else which makes the code more complex. Where strategy pattern creates less coupled code which is much simpler. By using Strategy pattern you can achieve more ways to configure code dynamically. So I would like to suggest you to use Strategy pattern.

Categories