0
\$\begingroup\$

I have the following HashMap :

  HashMap<String, String> days = new HashMap<String, String>(){
        days.put("MON", "9-5");
        days.put("TUE", "9-4");
        days.put("WED", "9-5");
        days.put("THU", "9-5");
        days.put("FR", "9-5");
        days.put("SAT", "Closed");
        days.put("SUN", "Closed");
};

I want to display following output :

MON-WED-THU-FRI : 9-5,
TUE: 9-4,
SAT-SUN : Closed

NOTE:The value of hashmap("9-5") may change depending upon the inputs from the admin panel.

I have done the below code but it's too lengthy:

    private void days() {

         String timing1 = null;
         String timing2 = null;
         String timing3 = null;
         String timing4 = null;
         String timing5 = null;
         String timing6 = null;
         String timing7 = null;

         ArrayList<String> time1 =new ArrayList<>();
         ArrayList<String> time2 =new ArrayList<>();
         ArrayList<String> time3 =new ArrayList<>();
         ArrayList<String> time4 =new ArrayList<>();
         ArrayList<String> time5 =new ArrayList<>();
         ArrayList<String> time6 =new ArrayList<>();
         ArrayList<String> time7 =new ArrayList<>();

         //iterating over the hash map and taking value ie time storing in respected variable

        for (Map.Entry<String, String> entry : days.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            System.out.println("key" + key + "Val" + value.toString());


            if (timing1 ==null || timing1.equals(value.toString())){
                timing1 = value.toString();
                continue;
            }

            if (timing2 ==null || timing2.equals(value.toString())){
                timing2 = value.toString();
                continue;
            }

            if (timing3 ==null || timing3.equals(value.toString())){
                timing3 = value.toString();
                continue;
            }

            if (timing4 ==null || timing4.equals(value.toString())){
                timing4 = value.toString();
                continue;
            }

            if (timing5 ==null || timing5.equals(value.toString())){
                timing5 = value.toString();
                continue;
            }

            if (timing6 ==null || timing6.equals(value.toString())){
                timing6 = value.toString();
                continue;
            }

            if (timing7 ==null || timing7.equals(value.toString())){
                timing7 = value.toString();

            }


        }


         //based on value from hash-map appending the key ie. days name(eg. MON) to the respected array-list

        for (Map.Entry<String, String> entry : days.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();


            if (timing1!=null && timing1.equals(value.toString())){

                time1.add(key);
                continue;
            }

            if (timing2!=null && timing2.equals(value.toString())){

                time2.add(key);
                continue;
            }

            if (timing3!=null && timing3.equals(value.toString())){

                time3.add(key);
                continue;
            }

            if (timing4!=null && timing4.equals(value.toString())){

                time4.add(key);
                continue;
            }

            if (timing5!=null && timing5.equals(value.toString())){

                time5.add(key);
                continue;
            }

            if (timing6!=null && timing6.equals(value.toString())){

                time6.add(key);
                continue;
            }

            if (timing7!=null && timing7.equals(value.toString())){

                time7.add(key);
               // continue;
            }

        }
\$\endgroup\$
1
\$\begingroup\$

The thing you need to do is commonly called "grouping", i.e. you iterate over a given dataset, take one property (the time in your case) and collect the entries with the same property in a useful structure.

Fortunately, java (8+) already can do this for you by streaming through the map entries and grouping them all automagically:

    Map<String, List<Map.Entry<String, String>>> grouped = days.entrySet().stream()
        .collect(Collectors.groupingBy(Map.Entry::getValue));

OK, the data-structure looks a little wierd here, because your list consists of map-entries, but this was the main work. If you print this result, you already get (format added manually):

{
     9-4=[TUE=9-4],
     9-5=[MON=9-5, WED=9-5, THU=9-5, FRI=9-5],
     Closed=[SAT=Closed, SUN=Closed]
}

... which is exactly what you need from a data perspective. Using a further iteration over this map which uses the time as a key and the old map's entries as values to format the respective output should be quite trivial.

BTW: to keep the order of the days, you should use a LinkedHashMap instead of a HashMap.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Types as interfaces

HashMap<String, String> days = new HashMap<String, String>(){

could be just

  Map<String, String> days = new HashMap<>() {

As a general rule, you code to the interface, not the implementation.

I also removed the unnecessary second declaration so as to leave it to the compiler to make it correct. Not only is this shorter, but it makes it easier to modify the map types in the future as you only need to do so in one place.

Avoid numbered variables

One of the problems that you have here is that you have to manually write out each relation. Instead, set up your data structures to handle that.

    private void days() {
        System.out.println(buildScheduleString());
    }

    private String buildScheduleString() {
        List<String> orderedDays
            = new ArrayList<>(Arrays.asList(
                "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"));

        Map<String, String> openHours = invertMap(days);

        List<String> lines = new ArrayList<>();
        for (String day: orderedDays) {
            String schedule = days.get(day);

            List<String> scheduledDays = openHours.get(schedule);
            if (scheduledDays != null) {
                StringBuilder builder = new StringBuilder();

                // unimplemented building of string

                lines.add(builder.toString());

                openHours.remove(schedule);
            }
        }

        // unimplemented return
    }

    public Map<String, String> invertMap(Map<String, String> map) {
        Map<String, String> result = new HashMap<>();

        for (Map.Entry<String, String> entry : map.entrySet()) {
            List<String> list = result.get(entry.getValue());
            if (list == null) {
                list = new ArrayList<String>();
                result.put(entry.getValue(), list);
            }

            list.add(entry.getKey());
        }

        return result;
    }

I left the parts that you didn't implement in the original code unimplemented here. Hint: if you are using Java 8, you could use String.join in both places.

This separates printing from the building of the string so as to allow reuse of buildScheduleString in other contexts in the future.

This creates a utility method (invertMap) that could be used in other contexts in the future. There may be a better name for it, as it is written to only work with Map<String, String>.

You could define orderedDays and openHours elsewhere. I defined them here, as it was the context you had.

By removing schedule after using it, we make it so that we don't repeatedly show the same line.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

The thing you should do is to inverse the map, keys become values and vice-versa, however I came up with something like this :

  public static void daysOfWeek() {
     Map<String, List<String>> ret = new HashMap<>();
    Map<String, String> days = new HashMap<>();
    days.put("MON", "9-5");
    days.put("TUE", "9-4");
    days.put("WED", "9-5");
    days.put("THU", "9-5");
    days.put("FR", "9-5");
    days.put("SAT", "Closed");
    days.put("SUN", "Closed");

    for (Map.Entry<String, String> next : days.entrySet()) {
        String key = next.getKey();
        String value = next.getValue();
        List<String> list;
        if (ret.containsKey(value)) {
            list = ret.get(value);
        } else {
            list = new ArrayList<>();
            ret.put(value, list);
        }
        list.add(key);

    }

    System.out.println(StringifyMap(ret));
}

private static String StringifyMap(Map<String, List<String>> map) {
    StringBuilder sb = new StringBuilder();

    for (Map.Entry<String, List<String>> next : map.entrySet()) {
        List<String> days = next.getValue();
        String hour = next.getKey();
        for (int i = 0; i < days.size(); i++) {

            sb.append(days.get(i));
            if (i < days.size() - 1)
                sb.append('-');
        }
        sb.append(':').append(hour);
        sb.append('\n');

    }

    return sb.toString();
}
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.