简体   繁体   中英

put and get for nested hashmap in java

I am really new to Java and I am trying to implement something using Hashmap.

The following code is what I declared first:

private HashMap<String, TreeMap<Object, Object>> submissions = new HashMap<String, TreeMap<Object, Object>>();;

And,

public Submission add(String unikey, Date timestamp, Integer grade) {

        // check the argument
        if(unikey == null || timestamp == null || grade == null) {
            throw new IllegalArgumentException("Null argument detected\n");
        }
}

this is what I am writing at the moment. Assuming that there are items called "person", "data" and "grade". Can someone please tell me how to put them in the nested hashmap? I finished writing the getter and setter for each of the items in another class called, MySubmissions.

The Submission is an interface written in another class that contain the following methods:

public String getPerson();
public Date getTime();
public Integer getGrade();

What I want to achieve is that, for example,

?.add("aaaa1234", df.parse("2016/09/03 09:00:00"), 10);
?.add("aaaa1234", df.parse("2016/09/03 16:00:00"), 20);
?.add("cccc1234", df.parse("2016/09/03 16:00:00"), 30);
?.add("aaaa1234", df.parse("2016/09/03 18:00:00"), 40);

Thanks!

(what I exactly want to achieve is, I want to add data into the hashmap. And then using another method called, getBestGrade, I want to get the best graded person among the list but I just want to know how to store into the hashmap first using put and get...)

Create an entity

public class Submission {

    private Date timestamp;

    private Integer grade;


    public Date getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(Date timestamp) {
        this.timestamp = timestamp;
    }

    public Integer getGrade() {
        return grade;
    }

    public void setGrade(Integer grade) {
        this.grade = grade;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Submission that = (Submission) o;

        if (timestamp != null ? !timestamp.equals(that.timestamp) : that.timestamp != null) return false;
        return grade != null ? grade.equals(that.grade) : that.grade == null;
    }

    @Override
    public int hashCode() {
        int result = timestamp != null ? timestamp.hashCode() : 0;
        result = 31 * result + (grade != null ? grade.hashCode() : 0);
        return result;
    }
}

Create a HashMap

private HashMap<String, Submission> map = new HasMap<>();

Do add

map.add("key", new Submission());

I think he wants to know how to store more than one Submission for each Person. You can do something like this:

import java.util.Date;
import java.util.HashMap;
import java.util.TreeMap;

public final class BestGrade
{
    private static final HashMap<String, TreeMap<Date, Integer>> SUBMISSIONS = new HashMap<String, TreeMap<Date, Integer>>();

    private BestGrade()
    {}

    public static void main(final String[] args)
    {
        // How to add
        add("Person1", new Date(), Integer.valueOf(1));
        add("Person1", new Date(), Integer.valueOf(10));
        add("Person1", new Date(), Integer.valueOf(20));
        add("Person2", new Date(), Integer.valueOf(1));
        add("Person3", new Date(), Integer.valueOf(30));
        add("Person3", new Date(), Integer.valueOf(40));

        // How to get best grade
        final Integer bestGradePerson1 = getBestGrade("Person1");
        final Integer bestGradePerson3 = getBestGrade("Person2");
        final Integer bestGradePerson2 = getBestGrade("Person3");

        System.out.println("Bestgrade Person1: " + bestGradePerson1);
        System.out.println("Bestgrade Person2: " + bestGradePerson2);
        System.out.println("Bestgrade Person3: " + bestGradePerson3);
    }

    public static void add(final String key, final Date timestamp, final Integer grade)
    {
        // TODO the same for timestamp and grade
        if (key == null || key.trim().isEmpty()) {
            throw new IllegalArgumentException("key must not be null");
        }

        // Get
        TreeMap<Date, Integer> submission = SUBMISSIONS.get(key);
        // Create your treemap if not already exists, before adding new value to avoid NullPointerException
        if (submission == null) {
            submission = new TreeMap<Date, Integer>();
            SUBMISSIONS.put(key, submission);
        }
        submission.put(timestamp, grade);
    }

    public static Integer getBestGrade(final String key)
    {
        Integer bestGrade = null;

        final TreeMap<Date, Integer> submission = SUBMISSIONS.get(key);
        if (submission == null) {
            // When no submission available, return null or any other value you wish to show there is no best grade
            return bestGrade;
        }

        for (final Integer grade : submission.values()) {
            if (bestGrade == null) {
                bestGrade = grade;
            }
            // Set new grade when values is higher than before
            else if (bestGrade.intValue() < grade.intValue()) {
                bestGrade = grade;
            }
        }
        return bestGrade;
    }
}

I'm just going to describe how to use a map of maps -- it's up to you to decide whether this is what you actually want to use. I'm going to use classes called A , B , C etc. -- you can substitute your own, including String or Submission if you like.

Make sure you have a firm understanding of a single-level Map before you tackle this -- how equals() and hashCode() are necessary for HashMap etc.

You can define a map of maps much as you have done:

Map<A, ? extends Map<B,C>> mapOfMaps;

In general, give variables a type of Map rather than HashMap or TreeMap -- you normally don't need any of the more specific methods of the implementation classes. You can always change up if you do. The ? extends Map<> ? extends Map<> part allows your map-of-maps to contains arbitrary implementations of Map .

You can instantiate this like this:

Map<A, ? extends Map<B,C>> mapOfMaps = new HashMap<>();
// or with explicit (unnecessary) type declarations:
Map<A, ? extends Map<B,C>> mapOfMaps = new HashMap<A, ? extends Map<B,C>>();

Now you have an empty map-of-maps. You can add a map to it:

Map<B,C> map = new HashMap<>();
mapOfMaps.put(new A(1), map);

Now you have a map-of-maps containing one empty map. Or you could add a map containing something:

Map<B,C> map = new HashMap<>();
map.put(b, c);
mapOfMaps.put(a, map);

Plausibly, you want to add items to a Map<B,C> when you don't know whether it exists. There's no short-cut here - you have to do:

void addToMapOfMaps(A a, B b, C c) {
   Map<B,C> map = mapOfMaps.get(a);
   if(map == null) {
      map = new HashMap<>();
      mapOfMaps.put(a,map);
   }
   map.put(b,c);
}

Note that this has problems if multiple threads are doing it at the same time.

Likewise if you're just reading, you have to handle missing elements at both levels:

C get(A a, B b) {
    Map<B,C> map = mapOfMaps.get(a);
    if(map == null) {
         return null;
    }
    return map.get(b);
}

(Or more compactly)

C get(A a, B b) {
    Map<B,C> map = mapOfMaps.get(a);
    return map == null ? null : map.get(b);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM