Steve
Steve

Reputation: 4701

Java can I map a variable to a method of an object

I have a string in the form "1=xyz,2=zyx,3=blah", and an object

public class Foo{
    String a,b,c
    /*gets and sets*/
}

I'd like to instantiate this object so that a = xyz, b = zyx, and c = blah. What I have so far is,

for(String[] split1 : originalString.split(","){
    for(String[] split2 : split1.split("="){
        if(split2[0] == 1){foo.setA(split2[1])}
        if(split2[0] == 2 {...}
    }
}

And what I want to know is, is there a cleaner way to do this than with a bajillion if statements? Is there a way to create a Map between the keys in the original list with setters in my pojo?

I found some older questions on this, but I was wondering if java 8 might have added something for this. I don't want to use Reflection (nor should I)

Upvotes: 0

Views: 301

Answers (3)

Saurabh
Saurabh

Reputation: 23

can use Regular Expression to blank out the not needed characters from the input string and then splitting it. Note the String elements in the output array might need trimming.

import java.util.regex.*;

public class StringRegex{
 public static void main(String[] args){
  String input = "1=xyz,2=zyx,3=blah";
  String notNeeded = "([1234567890=])";      //characters not needed 0-9 and =

  Pattern p = Pattern.compile(notNeeded);
  Matcher m = p.matcher(input);

  String output = m.replaceAll(" ");  //blank out the notNeeded characters
  System.out.println(output);         //gives:   xyz,  zyx,  blah

  String[] outputArr = output.split(",");

  for (String s:outputArr)
    System.out.println(s);
 }
}

Upvotes: 0

Steve
Steve

Reputation: 4701

I created a Map like 1="a", 2="b", 3="c", and used that to translate the keys into the pojo's field names.

Then I used the following from Gson

Gson gson = new Gson();
JsonElement jsonElement = gson.toJsonTree(responseMap);
Foo trade = gson.fromJson(jsonElement, Foo.class);

If I'd been allowed to use groovy, I'd simply use the default map-based constructor. Props to @chrylis for suggesting that approach.

Upvotes: 0

VGR
VGR

Reputation: 44404

Yes, you can use a Map<String, BiConsumer<Foo, String>>:

public class StringProcessor {
    private final Map<String, BiConsumer<Foo, String>> setMethods;

    public StringProcessor() {
        Map<String, BiConsumer<Foo, String>> methodMap = new HashMap<>();
        methodMap.put("a", Foo::setA);
        methodMap.put("b", Foo::setB);
        methodMap.put("c", Foo::setC);

        this.setMethods = Collections.unmodifiableMap(methodMap);
    }

    // ...

    public void processString(String originalString,
                              Foo foo) {

        for (String[] split1 : originalString.split(",")) {
            for (String[] split2 : split1.split("=")) {
                BiConsumer<Foo, String> setMethod = setMethods.get(split2[0]);
                setMethod.accept(foo, split2[1]);
            }
        }

    }
}

You could also use reflection, but that is best avoided, as reflection makes errors much harder to detect and it is less likely to be optimized at runtime by the JIT.

Upvotes: 2

Related Questions