简体   繁体   中英

java: check if an object's attribute exists in HashMap values

I have a HashMap with key of type Double and my custom object as value . It looks like this:

private static Map<Double, Incident> incidentHash = new HashMap<>();

The Incident object has following attributes: String date , String address , String incidentType .

Now I have a String date that I get from the user as input and I want to check if there exists any incident in the HashMap with that user inputted date. There can be many Incidents in the HashMap with the given date but as long as there's at least one Incident with the given date, I can do * something .

I can just iterate over all the values in the HashMap and check if a given date exists but I was wondering if there is any better and more efficient way possible without modifying the data structure.

You can use streams API (from Java8) as shown in the below code with inline comments:

String userInput="10-APR-2017";

Optional<Map.Entry<Double, Incident>> matchedEntry = 
  incidentHash.entrySet().stream().
  //filter with the condition to match
  filter(element -> element.getValue().getDate().equals(userInput)).findAny();

 //if the entry is found, do your logic
 matchedEntry.ifPresent(value -> {
            //do something here
 });

If you are looking for something prior to JDK1.8, you can refer the below code:

String userInput="10-APR-2017";
Set<Map.Entry<Double, Incident>> entries = incidentHash.entrySet();
Map.Entry<Double, Incident> matchedEntry = null;
for(Iterator<Map.Entry<Double, Incident>> iterator = entries.iterator(); 
                    iterator.hasNext();) {
    Map.Entry<Double, Incident> temp = iterator.next();
    if(temp.getValue().getDate().equals(userInput)) {
        matchedEntry = temp;
        break;
    }
}

Given your HashMap, NO , there is not another way of doing so without iterating that HashMap .

As for changing the structure, you could do as Map<String, List<Incident>> that way you would have a date as key and a List of incidents for that date, given your requirement: There can be many Incidents in the HashMap with the given date .

So this would be a O(1)

 //considering that the key is added when you have at least one incident
 if (yourHash.get("yourDateStringWhatEverTheFormatIs") != null)

You can use a TreeMap with your custom Comparator . In your Comparator compare the values of dates.

You would have to iterate through the map until you find a data that matches. Since you only need to know if any occurrences exist you can simply exit the loop when you find a match instead of iterating the rest of the map.

You can only keep a second Hash/TreeMap that matches the attribute to the object, so you can also check this attibute qickly. But you have to curate one such map for each attribute you want to access quickly. This makes it a bit more complex and use more memory, but can be much much faster.

If this is not an option the stream API referenced in other answers is a nice and tidy way to iterate over all objects to search for an attribute.

private static Map<Double, Incident> incidentHash = new HashMap<>();
private static Map<String, List<Incident>> incidentsPerDayMap = new HashMap<>();

Given that you don't want to iterate the Map and currently it's the only way to get the required value, I would recommend recomment another Map that contains Date as key and List<Incident> as value. It can be a TreeMap , eg:

Map<Date, List<Incident>> incidents = new TreeMap<>();

You can put the entry in this Map whenever an entry is added into the original Map , eg:

Incident incident = ;// incident object
Date date; //Date
incidents.computeIfAbsent(date, t -> new ArrayList<>()).add(incident);

Once the user inputs the Date , you can get all the incidents belonging to this date just by incidents.get() . Although that will give you a list and you still need to iterate over it, it will contain a lot less elements and get method in TreeMap will guarantee you log n complexity as it is sorted. So, your search operation will be much more efficient.

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