I am new to Java. I have lots of multiple if-else statements. For code optimization purpose I need to write one function for all if else logic.
if (obj.getJSONObject("page_1").has("city")) {
sn.city = (String) obj.getJSONObject("page_1").get("city").toString();
} else {
sn.city = null;
}
// param 2 - locality
if (obj.getJSONObject("page_1").has("locality")) {
locality = (String) obj.getJSONObject("page_1").get("locality").toString();
} else {
locality = null;
}
I have like 110 if -else statements. I don't have any idea how to optimize the code.
I might write a function something like:
static String getToStringOrNull(JSONObject parent, String key) {
return parent.has(key) ? parent.get(key).toString() : null;
}
which you can then call like
sn.city = getToStringOrNull(obj.getJSONObject("page_1"), "city");
locality = getToStringOrNull(obj.getJSONObject("page_1"), "locality");
I think the best use would be this notation (ternary operator):
sn.city = (obj.getJSONObject("page_1").has("city")) ?
(String) obj.getJSONObject("page_1").get("city").toString() : null;
The part before ? stands for the if-statement, the second part if the condition was fulfilled and the last part otherwise.
For all direct fields of your class, you may use reflection (and you could do the same work on the sn object if you want ) :
Class aClass = this.getClass();
Field[] fields = aClass.getFields();
for (Field field : fields) {
String value = (obj.getJSONObject("page_1").has(field.getName())) ?
(String) obj.getJSONObject("page_1").get(field.getName()).toString() : null;
field.set(this, value);
}
Related
I have a object and i get some fields from it, i made a method with a switch statement, the idea was make it generic and just call this method through parameters but now I´m not sure.
The options are
private String getCode(Row row, String code) {
String result;
switch (code) {
case code1:
result = row.getString("constant1");
break;
case code2:
result = row.getString(constant2);
break;
case code3:
result = row.getString(constant3);
break;
case code4:
result = row.getString(constant4);
break;
default:
result = null;
}
return result;
}
or
private String getcode1(Row row){
return row.getString("constant1")
}
private String getcode1(Row row){
return row.getString("constant2")
}
private String getcode1(Row row){
return row.getString("constant3")
}
private String getcode1(Row row){
return row.getString("constant4")
}
I wand to use the better way, I´m a little confuse
The answer is neither of the them.
What you have here is a value conversion process. How this works? Well, as far I understand, you need to store the data in form of key-value pair where key must be unique. So this is the definition of a HashMap in java.
Also, because you are using Switch I'm assuming that you can identify your data with some unique key. This meas for each code there is only one constant. But how we can apply this to my issue? Well, I think you have a collection of data from where you extracted a single row. Now, from this row you want to access to a value (lets call it codeValue) using a constant, but to get this constant you need a code. Like this: code->constant->codeValue
How can I implement this??
Well, we gonna need a HasMap() called constants, which defines its keys a codes and the values as constants. Now you easily get each constant if you know its code. Obviously, if you get the constant you can also get the codeValue of each `row, like this:
public class TestClass {
public static void main(String[] args) {
// Create a HashMap object called constants
Map<String, String> constants = new HashMap<String, String>();
// Add keys and values (code, constant)
constants.put("code1", "constant1");
constants.put("code2", "constant2");
constants.put("code3", "constant3");
constants.put("code4", "constant4");
System.out.println(constants);
Row row = loadRow();
String code = loadCode();
//How to use it
String result = getCodeValue(row, code);
System.out.println(result);
}
// Now you get the code from the Map
private String getCodeValue(Row row, String code) {
return row.getString(constants.get(code));
}
}
In case your input code is different than constant, I will suggest the following approach. Create an Enum mapping code and constant.
public enum Mapping {
MAPPING_FIRST("code1", "constant1"),
MAPPING_SECOND("code2", "constant2");
private String code;
private String constant;
// constructor and getters
public static Mapping getMappingFromCode(String code){
return Arrays.stream(Mapping.values())
.filter(mapping -> mapping.getCode().equals(code))
.findFirst()
.orElse(null);
}
}
Now, create a method to access value from row.
private String getValue(Row row, String code) {
Mapping mapping = Mapping.getMappingFromCode(code);
if(mapping == null){
return null;
}
return row.getString(mapping.getConstant());
}
This question is little bit to much, but I will try to explain best I could. For me second option is no no at all. Why? You are making methods that you will have to sort out with some if/else statements anyway, for example:
if (code.equals(code1))
someString = getcode1(row);
else if (code.equals(code2))
somestring = getcode2(row);
else if (code.equals(code3))
someString = getcode3(row);
else
someString = getcode4(row);
Why not use this:
if (code.equals(code1))
someString = row.getString("content1");
else if (code.equals(code2))
somestring = row.getString("content2");
else if (code.equals(code3))
someString = row.getString("content3");
else
someString = row.getString("content4");
The first one I can see being used, but there is alternative there. Give us entire minimal requirement code with entire class and methods and we could help you far more than using these snippets of code.
Create an enum for mapping of code and constant. In that enum, create a generic method where you can get code just passing through parameter.
public enum MyEnum {
CODE1("constant1"), CODE2("constant2");
private String constant;
public String getConstant() {
return constant;
}
private MyEnum(String constant) {
this.constant = constant;
}
private static String getConstant(String code) {
return Arrays.stream(MyEnum.values()).filter(mapping -> mapping.name().equalsIgnoreCase(code))
.map(e -> e.getConstant()).findAny().orElse(null);
}
public static String getCode(Row row, String code) {
String constant = getConstant(code);
return constant != null ? row.get(constant) : null;
}
}
You can get code from row object by calling genric method getCode().
MyEnum.getCode(row, "code1")
I have a class like this..
Class A {
public void someNullCheckingMethod(Student stu) {
if (stu.getName() != null) {
String name = stu.getName();
} else {
// get name from other source(its something like
// fallback)
}
if (stu.getId() != null) {
String id = stu.getId();
} else {
// get id from other source(its something like
// fallback)
}
if (stu.getAddress() != null) {
String address = stu.getAddress();
} else {
// get address from other source(its something like
// fallback)
}
if (stu.getCity() != null) {
String city = stu.getCity();
} else {
// get city from other source(its something like
// fallback)
}
if (stu.getGender() != null) {
String gender = stu.getGender();
} else {
// get gender from other source(its something like
// fallback))
}
}
}
is there a way to avoid too many if statements? As you can see here I am checking null condition for each property but i don't want many checks to get desired result just want to reduce if conditions as well as want to get same desired result whatever I will get by putting all these if conditions.
Since you don't provide any context there's a few things you can do based on some assumptions.
Assumption one:
if the values are initialized as null
String name;
// or
String name = null;
Then you can just assign the values and ignore if the fields are null or not since the class members are null already.
String name = stu.getName(); // String name = "Some Name" OR null, depending on return value of method
Assumption two:
If you just want to avoid the if statements you can go with ternary operators
String name = stu.getName() != null ? stu.getName() : null; // Or some other default value
There are a few other methods that pops into my mind as well but without more context they are a bit useless at this point.
You could at least reduce the "verbosity" with Optional.
String name;
if (stu.getName() != null) {
name = stu.getName();
} else {
name = "default"
}
Would become
String name = Optional.ofNullable(stu.getName()).orElse("default");
Th choice is yours to return an Optional directly from the POJO Student for any value that could be null.
This would give a cleaner solution :
String name = stu.getName().orElse("default");
If getName looks like :
public Optional<String> getName(){
return Optional.ofNullable(name);
}
If using an external library is an option, then you should take a look at Dozer or MapStruct.
I have below block of code
if(Objects.nonNull(isMine)) {
if (isMine) {
this.books= // gets it from the database;
} else {
this. books= // gets it from the database
}
} else {
this. books = // gets it from the database
}
isMine - is a Boolean object
I tried with switch case by converting isMine to a string as below
String.valueOf(isMine)
But didn't work .Suggest a better and faster way to implement above code in java.
You can flatten your if-else statement by using else if:
if(isMine == null) {
books = allList;
} else if(isMine) {
books = myList;
} else {
books = notMyList;
}
Another approach would be to sperate the checks into methods:
public List<Book> getBookList(Boolean isMine) {
return isMine == null ? allList : getBookList(isMine.booleanValue());
}
public List<Book> getBookList(boolean isMine) {
return isMine ? myList : notMyList;
}
You can use Optional in this case:
Boolean isMine = null;
String str = "";
Optional<Boolean> optional = Optional.ofNullable(isMine);
str = optional.map(i -> i ? "a" : "b").orElse("c");
System.out.println(str);
So it will be something like:
this.books = optional.map(i -> i ? valForTrue : valForFalse).orElse(valForNull);
this.books = isMine != null ? (isMine ? this.myList : this.notMyList) : this.allList;
Using ternary operator inside of ternary operator e.g.
Do not even think about performance in your case, that's tiny.
Your current way looks good. And you have an answer with flatten way and nested ternary too.
If you still want to learn how to use switch in this case (please do not put this code in production. posting for showing you a way)
Correct way to achieve using String.valueOf(isMine) is
switch ( String.valueOf(isMine) ) {
case "null":
//TODO
break;
case "true":
//TODO
break;
case "false":
//TODO
break;
}
With pattern matching provided by vavr.io it can get very clean:
List<Books> output = Match(input).of(
Case($(true), dbCallX()),
Case($(false), dbCallY()),
Case($(), dbCallZ()));
I want to make the following code better, but cannot get a good idea.
Is there any way to solve this?
I just create a Android project and use greenDAO greendao to create tables by Class.
for (Field field : fields) {
fieldName = field.getName();
// we don't need this.
if ("serialVersionUID".equals(fieldName)) {
continue;
}
type = field.getType();
// primary key, just auto increment.
if ("id".equals(fieldName)) {
entity.addIdProperty().autoincrement();
continue;
}
// other fields
/*
* this is the problem what I want to solve.
* I thought it's too bad to read and have a bad looking.
*/
if (type.equals(String.class)) {
entity.addStringProperty(fieldName);
}else if (type.equals(Integer.class)) {
entity.addIntProperty(fieldName);
}else if (type.equals(Double.class)) {
entity.addDoubleProperty(fieldName);
}else if (type.equals(Float.class)) {
entity.addFloatProperty(fieldName);
}else if (type.equals(Long.class)) {
entity.addLongProperty(fieldName);
}else if (type.equals(Byte.class)) {
entity.addByteProperty(fieldName);
}else if (type.equals(Short.class)) {
entity.addShortProperty(fieldName);
}else if (type.equals(Boolean.class)) {
entity.addBooleanProperty(fieldName);
}else if (type.equals(Character.class)) {
entity.addStringProperty(fieldName);
}else if (type.equals(Date.class)) {
entity.addDateProperty(fieldName);
}
}
Java 8 solution: create a static Map of "adder methods" where each possible property type will be associated with corresponding lambda:
static final Map<Class<?>, BiConsumer<Entity, String>> ADDERS = new IdentityHashMap<>();
{{
ADDERS.put(String.class, Entity::addStringProperty);
ADDERS.put(Integer.class, Entity::addIntegerProperty);
//...
}}
then, for each field:
ADDERS.get(type).accept(entity, field.getName());
Class objects can be compared using == rather than .equals because there is only ever one instance per class.
It is occasionally necessary to have a sequence of nested if statements like this to find the right Class object, and this obviously very ugly (see the source code for Arrays.deepToString for a real example of this).
There are other solutions involving Map, or switching on type.getSimpleName(), however I would personally stick to the simple solution even if it is long-winded.
You could use more reflection.
String typeStr = type.getSimpleName();
switch(typeStr) {
case "Integer": typeStr = "Int"; break;
case "Character": typeStr = "String"; break;
}
Method m = enttity.getClass().getMethod("add" + typeStr + "Property", String.class);
m.invoke(entity, fieldname);
How do I print result from if statements in Java? This result should be assigned to some variable, that variable should print result in string. Currently, my code is like this. I want to store simple & extended into a single variable, so that i should able to call this variable anywhere in the program. There it should print "simple" or "extended".
if(loc[i]==1) {
System.out.println("simple");
}
else if(loc[i]>1) {
System.out.println("extended");
}
You mean like this:
String mode;
if(loc[i]==1)
mode = "simple";
else if(loc[i]>1)
mode = "extended";
else
mode = "error";
System.out.println(mode);
How about
String s = (loc[i]==1 ? "simple" : (loc[i]>1 ? "extended" : null));
If I understood you correctly you need following
private static final SIMPLE_STRING = "simple";
private static final EXTENDED_STRING = "extended";
if(loc[i]==1) {
System.out.println(SIMPLE_STRING );
}
else if(loc[i]>1) {
System.out.println(EXTENDED_STRING );
}
String type;
if( loc[i] == 1 )
{
type = "simple";
}
else if( loc[i] > 1)
{
type = "extended";
}
else
{
type = null;
}
// variable 'type' can now be used in the same block of code
System.out.println( type );
If you want to use this variable anywhere in your program, you will have to either declare the variable at a higher scope to be accessible or return this variable from this code block.