Paul Harper
Paul Harper

Reputation: 51

Iterate over a HashMap with multiple values per key

I am currently learning sets and maps through university (still using Java 7).

They have given us a half finished to-do list app to complete. Currently the to-do list takes three String local variables to allow the user to state a job (aJob), a time to do it (aTime) and a date to do it (aDate).

The app also has an instance variable (today) that holds todays date.

I need to come up with a way to check the HashMap for any tasks that are due today. So I need to be able to query just the HashMap values attributed by the aDate local variable.

I know that to iterate Maps that I can place the keys or the values into a Set and then iterate over the set - not a problem. But if I use the values() method (within the Map class) to put these into a set - it places all three Strings per key into the set. I just want to move the aDate values into a set.

Any ideas?

I only seem to be able to find examples where the Maps have just a single Key and Single Value. This list has a single key and three values per key.

Any pointers would be good?

Kind Regards

Edit.....

Just thought I would add some code to help as there have been several different approaches - which I am all very greatful for. But not sure if they suit my needs....

The Job Class is constructed as such...

public Job(String aJob, String aDate, String aTime)
{
  Job = aJob;
  date = aDate;
  time = aTime;
}

I then create the map within the instance declarations for the To Do List class....

Map<Integer, Job> toDoList = new HashMap<>();

So I need to know the best way to iterate over this map, but it is only the Job attribute 'aDate' that is possibly going to hold the value I am after.

Not sure if that helps at all?

Kind Regards

Upvotes: 0

Views: 4150

Answers (3)

Kristin
Kristin

Reputation: 1391

If you can't use a custom class, as suggested by Toisen, maybe HashMap<String, HashMap<String, ArrayList<String>>> could do the trick for you.

I've added a sample of how to use it (as well as populating it with some random data)

public class FunkyMap {
    private HashMap<String, HashMap<String, ArrayList<String>>> jobs;

    // For random data
    private String[] job = {"EAT", "SLEEP", "FART", "RELAX", "WORK"};
    private String[] time = {"MORNING", "BEFORENOON", "NOON", "AFTERNOON", "EVENING", "MIDNIGHT"};
    private String[] date = {"FIRST", "SECOND", "THIRD", "FOURTH"};

    public FunkyMap() {
        jobs = new HashMap<>();

        // To populate some random data
        Random r = new Random();
        for(int i = 0; i < 20; i++) {
            String d = date[r.nextInt(date.length)];

            if(jobs.containsKey(d)) {
                HashMap<String, ArrayList<String>> inner = jobs.get(d);
                String t = time[r.nextInt(time.length)];

                if(inner.containsKey(t)) {
                    inner.get(t).add(job[r.nextInt(job.length)]);
                } else {
                    List<String> s = Arrays.asList(new String(job[r.nextInt(job.length)]));
                    inner.put(t, new ArrayList<String>(s));
                }
            } else {
                jobs.put(d, new HashMap<String, ArrayList<String>>());
            }
        }

        // Actual iteration over date => time => jobs
        Iterator<String> i = jobs.keySet().iterator();
        while(i.hasNext()) {
            String iKey = i.next();
            HashMap<String, ArrayList<String>> inner = jobs.get(iKey);

            System.out.println("Jobs scheduled for " + iKey);

            Iterator<String> j = inner.keySet().iterator();
            while(j.hasNext()) {
                String jKey = j.next();
                ArrayList<String> actualJobs = inner.get(jKey);

                System.out.println("\tAt " + jKey);

                for(String s : actualJobs) {
                    System.out.println("\t\tDo " + s);
                }
            }
        }
    }

    public static void main(String[] args) {
        new FunkyMap();
    }
}

I took the liberty to assume that dates were unique, and time was unique per date, while a time could hold any number of jobs including duplicates. If the last assumption with jobs is not true, you could swap ArrayList<String> with Set<String>.

Upvotes: 1

FrederikVH
FrederikVH

Reputation: 486

If really the only structure you're allowed to use is a Map where each key has 3 values (which is the case if I understand correctly), of which only one is a Date, you technically could do the following:

map.values()
    .stream()
    .filter(Date.class::isInstance)
    ...whatever else you want to do

The other suggested solutions are far better though, design wise.

Upvotes: 1

Toisen
Toisen

Reputation: 39

Just create a class that holds all data that you need. E.g. If you need something strange like Map<String, Tuple<String, Integer, Date>> just make a new class that holds the Tuple:

    class TupleHolder {
    private String firstValue;
    private Integer secondValue;
    private Date thirdValue;

    // get/set here...
}

and use it: Map<String, TupleHolder>

Upvotes: 0

Related Questions