简体   繁体   English

java:检查HashMap值中是否存在对象的属性

[英]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 . 我有一个HashMap,其类型为Double ,我的自定义对象为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 . Incident对象具有以下属性: String dateString addressString 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. 现在,我有一个从用户那里得到的String date作为输入,我想检查在HashMap中是否存在任何使用该用户输入日期的事件。 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 . 给定日期的HashMap中可以有很多事件,但是只要给定日期至少有一个事件,我就可以做某事

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. 我可以遍历HashMap中的所有值并检查是否存在给定的日期,但是我想知道是否存在不修改数据结构的更好,更有效的方法。

You can use streams API (from Java8) as shown in the below code with inline comments: 您可以使用流API(来自Java8),如以下代码所示,并带有内联注释:

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: 如果您正在寻找JDK1.8之前的版本,则可以参考以下代码:

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 . 给定您的HashMap, ,没有其他方法可以对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 . 至于更改结构,您可以将Map<String, List<Incident>>用作方法,这样就可以将date作为键,并根据需要设置该日期的事件ListThere can be many Incidents in the HashMap with the given date

So this would be a O(1) 所以这将是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 . 您可以将TreeMap与自定义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. 您只能保留第二个将属性与对象匹配的Hash / TreeMap,因此您也可以快速检查此属性。 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. 如果这不是一个选择,则在其他答案中引用的流API是一种迭代所有对象以搜索属性的好方法。

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. 鉴于您不想iterate Map,并且当前它是获取所需值的唯一方法,因此我建议您重新推荐另一个包含Date作为键和List<Incident>作为值的Map It can be a TreeMap , eg: 它可以是TreeMap ,例如:

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: 你可以put这个入口Map ,每当项被添加到原来的Map ,例如:

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() . 用户输入Date ,您可以仅通过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. 尽管这将为您提供一个list并且您仍然需要对其进行迭代,但是它将包含更少的元素,并且TreeMap get方法将确保您在排序时log n复杂性。 So, your search operation will be much more efficient. 因此,您的搜索操作将更加高效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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