1

I have 7 boolean variables in a java object for the days of the week (Monday through Sunday). I am trying to find a succinct way from a for loop of a list of days to say the following:

    private boolean isWorkDay(String day, Object pgMasterTaskList) {
        if(day=="Sunday" && pgMasterTaskList.Sunday==true) {
            return true;
        }
        if(day=="Monday" && pgMasterTaskList.Monday==true) {
            return true;
        }
        if(day=="Tuesday" && pgMasterTaskList.Tuesday==true) {
            return true;
        }
        if(day=="Wednesday" && pgMasterTaskList.Wednesday==true) {
            return true;
        }
        if(day=="Thursday" && pgMasterTaskList.Thursday==true) {
            return true;
        }
        if(day=="Friday" && pgMasterTaskList.Friday==true) {
            return true;
        }
        if(day=="Saturday" && pgMasterTaskList.Saturday==true) {
            return true;
        }
        else return false;
    }

I'm hoping I can minimize the repetition with something like...

private boolean isWorkDay(String day, Object pgMasterTaskList) {
        if(pgMasterTaskList.getVariableByName(day)==true) {
            return true;
        }
        else return false;
    }

My thought is to use reflection to check if the value of the variable named "Monday" and so on, but I'm not sure how to use it in such a way.

Edit

I have submitted an answer that works for my specific case. A little more detail...

I'm writing this information out to a pdf so I was handling string comparisons because I have to map them to field names in the pdf. So I was trying to be consistent. ANY combination of days could be a work day. I think this leaves me with 128 combos? (2^7). The information is being fed in by csv so I wanted to read day in as a string since it's coming in as such.

8
  • 8
    Note: Comparing strings using == in Java does not do what you think it does. Use equals instead. See: How do I compare strings in Java? Commented May 16, 2020 at 17:07
  • 1
    You may also consider to refactor to DayOfWeek Commented May 16, 2020 at 17:10
  • 1
    Use like this day.equalsIgnoreCase("Sunday"), it will solve your problem. Commented May 16, 2020 at 17:10
  • 1
    Instead of 7 booleans use an EnumSet<DayOfWeek>. Commented May 16, 2020 at 17:13
  • is every day a workday? Commented May 16, 2020 at 17:17

5 Answers 5

2

If you can modify your task list object to hold a Set of working days rather than 7 Boolean values, you don’t even need a loop. A table lookup in linear time will do.

    DateTimeFormatter dowFormatter = DateTimeFormatter.ofPattern("cccc", Locale.ENGLISH);

    EnumSet<DayOfWeek> workdays = EnumSet
            .of(DayOfWeek.MONDAY, DayOfWeek.TUESDAY, DayOfWeek.THURSDAY);
    String day = "Tuesday";

    DayOfWeek dow = dowFormatter.parse(day, DayOfWeek::from);
    boolean isWorkDay = workdays.contains(dow);

    System.out.println("Is work day? " + isWorkDay);

Output from the example:

Is work day? true

An EnumSet is implemented as an array of Boolean values.

I trust you to fit the EnumSet into your object and wrap the code in a method similar to what you are doing in the question.

The pattern letter c that I am using in the format pattern string used for defining the formatter for day of week is not often used. Frankly I am in doubt whether it is correct to use it here. According to the documentation it gives us the standalone form of the localized day of week text. Since the day of week standa alone — it is not part of a date string — I figured it might be right. If not, use the more common EEEE. At least for English, both work.

Edit: Even though your 7 boolean values come from a CSV file, I would probably still use the set approach. For initializing the set, I don’t think I’d resort to reflection, but accept 7 if statemnts (here condensed more than most of us do in real code):

    boolean sunday = false;
    boolean monday = true;
    boolean tuesday = true;
    boolean wednesday = false;
    boolean thursday = true;
    boolean friday = false;
    boolean saturday = false;

    Set<DayOfWeek> workdays = EnumSet.noneOf(DayOfWeek.class);
    if (sunday) workdays.add(DayOfWeek.SUNDAY);
    if (monday) workdays.add(DayOfWeek.MONDAY);
    if (tuesday) workdays.add(DayOfWeek.TUESDAY);
    if (wednesday) workdays.add(DayOfWeek.WEDNESDAY);
    if (thursday) workdays.add(DayOfWeek.THURSDAY);
    if (friday) workdays.add(DayOfWeek.FRIDAY);
    if (saturday) workdays.add(DayOfWeek.SATURDAY);

    System.out.println(workdays);

[MONDAY, TUESDAY, THURSDAY]

Edit 2:

Here is a simple example of converting a line of Boolean values from a CSV file to an EnumSet<DayOfWeek>.

    String lineFromCsv = "false;true;true;false;true;false;false";

    String[] workDayStrings = lineFromCsv.split(";");
    Set<DayOfWeek> workdays = EnumSet.noneOf(DayOfWeek.class);
    // Sunday
    if (Boolean.valueOf(workDayStrings[0])) {
        workdays.add(DayOfWeek.SUNDAY);
    }
    // Monday through Saturday
    for (int i = 1; i < workDayStrings.length; i++) {
        if (Boolean.valueOf(workDayStrings[i])) {
            workdays.add(DayOfWeek.of(i));
        }
    }
    System.out.println(workdays);

[MONDAY, TUESDAY, THURSDAY]

Link

Sign up to request clarification or add additional context in comments.

3 Comments

Without me giving further explanation this answer is great. Unfortunately that "workdays" set is coming in as a csv and could change week by week. I have found an answer that worked for me elsewhere but I really appreciate your input!
Thanks for reporting back. It’s probably a matter of taste more than anything else. I think I’d still want to stick to the EnumSet approach. See my edit.
@MatthewC I have added a simple example of converting the Boolean values from the CSV file to an EnumSet — with a loop (you may alternatively use a stream operation, left to the reader).
1

You can use the Object class .getClass().getFields() method to fetch all the variables in a class or use specific .getClass().getField("variableName") to fetch a particular variable.

The java reflection api will allow to fetch the variable as a Field (java.lang.reflect)

  private boolean isWorkDay(String day, Object pgMasterTaskList)
      throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
    Object obj = null;
    if (pgMasterTaskList.getClass().getField(day).get(obj).equals(true)) {
      return true;
    } else
      return false;
  }

The line Object obj = null; in above is just a placeholder to fetch of the variable using .get().

However, this will work only when the value for day parameter exactly matches the variable name as defined in pgMasterTaskList class. If you want a fetch based on case-insensitive scenario you can use the .getFields() method. Below is an example for the same:

  private boolean isWorkDay(String day, Object pgMasterTaskList) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
    Object obj = null;
    for (Field field : pgMasterTaskList.getClass().getFields()) {
      if (day.equalsIgnoreCase(field.getName())) {
        obj = field.get(obj);
        if ((boolean) obj == true)
          return true;
      }
    }
    return false;
  }

The .get(obj) will return an object of class type of your variable (your variable was boolean, then return obj will be of type boolean).

Comments

1

I have found an answer to my question using the following method:

  public static Object getValueOf(Object clazz, String lookingForValue)
      throws Exception {
    Field field = clazz.getClass().getField(lookingForValue);
    Class clazzType = field.getType();
    if (clazzType.toString().equals("double"))
      return field.getDouble(clazz);
    else if (clazzType.toString().equals("int"))
      return field.getInt(clazz);
    // else other type ...
    // and finally
    return field.get(clazz);
  }

I call it as following now:

    private boolean isWorkDay(String day, PlanGridMasterTaskList pgMasterTaskList) throws Exception {
        System.out.println(getValueOf(pgMasterTaskList, day));
        if ((boolean) getValueOf(pgMasterTaskList, day)) {
            return true;
        }
        else
            return false;
    }

I found it at this link: https://www.rgagnon.com/javadetails/java-0038.html

Thank you to everyone who took the time to respond (and so quickly at that!).

3 Comments

Thanks for answering your own question. It’s not completely clear to me how this code fits into the code in the question, though…?
@OleV.V. Woops! It would be helpful if I make reference to that original method, wouldn't it? Haha. I've made the edit above.
@MatthewC, in above approach, I can suggest that you don't need multiple if-else in getValueOf() method. You can directly return field.get(clazz) and type-cast the returned object where ever you intend to use it. Current code might be not useful as all methods in field viz. getInt, getDouble return an Object which you need to cast at the getValue() calling point. Refer to this line if ((boolean) getValueOf(pgMasterTaskList, day)) where you cast the value to boolean. So, you can remove the multiple if-else and just have field.get(clazz)
0

You must use reflection for this:

private boolean isWorkDay(String day, Object pgMasterTaskList) throws NoSuchFieldException, NullPointerException, SecurityException {
    return pgMasterTaskList.getClass().getField(day);
}

NOTE: callers must handle the cases where they pass a day that's null or just wrong, or the boolean member aren't public.

Comments

0

Try creating an enum and then you method logic would simply look like below,

public class WeekMap {

    public static void main(String[] args) {
        System.out.println(isWorkDay("SUNDAY",WeekDays.SUNDAY));
        System.out.println(isWorkDay("sunday",WeekDays.SUNDAY));
        System.out.println(isWorkDay("sunday",WeekDays.SATURDAY));
        System.out.println(isWorkDay("ABS",WeekDays.SATURDAY));
    }

    private static boolean isWorkDay(String day, WeekDays pgMasterTaskList) {
        WeekDays day1 = WeekDays.valueOf(day.toUpperCase()); // Fetch the mapped day for the string
        try{
            day1 = WeekDays.valueOf(day.toUpperCase());
        } catch (IllegalArgumentException iex) {
            iex.printStackTrace(); // this can be suppress
        }
        return day1 == pgMasterTaskList;
    }
}

enum WeekDays{ // Create enum for week day names
    SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.