Home > database >  Resolving value with different behavior, preferably without if else
Resolving value with different behavior, preferably without if else

Time:06-20

Here is what I'm trying to do

First initiate an optional variable, then do procedure A. if procedure A yield null then try procedure B and so on. if all the procedure still yield null, throw exception

#pseudocode

Optional<> someVariable;

if (someVariable is empty):
  fetch value through procedure A
  assign to someVariable
if (someVariable is empty):
  fetch value through procedure B
  assign to someVariable
.
.
.
if still empty:
  throw exception

The problem is I don't really want to go through procedure B if procedure A already resolve the value and I don't think it is scalable if more procedure is added any input?

CodePudding user response:

This has no else

public static void main(String[] args) {

    Integer result = null;
    if ((result = procA()) == null && (result = procB()) == null){
        System.out.println("throw ex");
    }
}

static Integer procA ()  {
    
    System.out.println("procA");
    return null;
}

static Integer procB () {
    System.out.println("procB");
    return null;
}

Try changing the values of what the methods return.

CodePudding user response:

A slightly verbose but hopefully readable approach:

Object someVariable = Stream.of(initialValue)
    .map(obj -> obj == null ? procedureA() : obj)
    .map(obj -> obj == null ? procedureB() : obj)
    .findFirst()
    .orElseThrow(NoSuchElementException::new); // or whatever exception you want

CodePudding user response:

If your procedures are relatively simple and can be declared as Runnables. Then we can create a list of Runnables and execute the run method with a for loop:

private class ProcedureA implements Runnable {
    @Override
    public void run() {
        someVariable = try fetching value
    }
}

// private class ProcedureB/C/D/E implements Runnable {}

List<Runnable> procedures = List.of(new ProcedureA(), new ProcedureB(), ...);
for (Runnable procedure : procedures) {
    if (someVariable.isPresent()) {
        break;
    }
    procedure.run();
}

if (someVariable.isEmpty()) {
    throw exception;
}

If the procedures are somewhat complicated, and will return values or take arguments, then we can use Callable or define a custom Procedure interface with a running method.

public interface Procedure {
   V running(arg1, arg2);
}

public class ProcedureA implements Procedure {
    @Override
    public V running(arg1, arg2) {}
}

List<Procedure> procedures = List.of(new ProcedureA() ...);

CodePudding user response:

With JDK 11 (probably JDK 8 ):

public class MyClass {

  private Integer procedureA() {
    return ...
  }

  private Integer procedureB() {
    return ...
  }

  ...
  
  private final List<Supplier<Integer>> procedures = List.of(
    this::procedureA,
    this::procedureB,
    // ... as many as you want
  );

  public Optional<Integer> readValue() {
    Integer someValue =  procedures
            .stream()
            .map( Supplier::get )
            .filter( Objects::nonNull )
            .findFirst()
            .orElseThrow( () -> new RuntimeException( "Exception!" )   );
   // I don't think it makes sense to return an optional in this case
   // but you can do it if you want to
   return Optional.of(someValue);
  }
}

This is pretty much the same approach everybody else suggested, but with the latest Java you can write code that's much more compact and understandable than the one I've seen in the other answers.

CodePudding user response:

Here is an "old dog" answer. The idea is to put the methods into different objects, and each object into a collection, and loop through the collection:

package fooDemo;

public interface Fooable<T> {
    public T foo (T thing, String control); 
}

package fooDemo;

import java.util.ArrayList;

public class FooTest {
    
    private  ArrayList<Fooable> stuff = new ArrayList<> ();
    public FooTest () {
        
        stuff.add (new Fooable<String> () 
           {@Override
           public String foo (String str, String line) {
               if (str == null && line.contains("FEE FIE FOE FUM"))
                   str = "Jack and the Beanstalk";
                   return str;
           } }); 
        
        stuff.add (new Fooable<String> () 
           {@Override
           public String foo (String str, String line) {
               if (str == null && line.contains("This bed is too soft."))
                   str = "Goldilocks and the Three Bears";
               return str;
           } }); 
        
                
        stuff.add (new Fooable<String> () 
           {@Override
           public String foo (String str, String line) {
               if (str == null && line.contains
                     ("I'll blow your house down"))
                   str = "The Three Little Pigs";
               return str;
           } }); 
        
                stuff.add (new Fooable<String> () 
           {@Override
           public String foo (String str, String line) {
               if (str == null && line.contains
                      ("Such big teeth you have"))
                   str = "Little Red Riding Hood";
               return str;
           } }); 
    }
    
    public String testAndSet (String str, String line) 
           throws IllegalArgumentException {
        for  (int i = 0; i < stuff.size();   i) {
            { str  = (String) (stuff.get(i).foo(str, line));
            if (str != null) break;
            }
        }
        if (str == null) throw new IllegalArgumentException 
                 ("Unable to foo "  str);
        return str;
    }
    
    public static void main(String[] args) {
        System.out.println (new FooTest()
          .testAndSet(null, "Such big teeth you have"));
    }    
}
  • Related