简体   繁体   中英

Implementing a generic map with java

I understood that you can pass pretty much anything to a method with an object. I am trying to write an assert function that checks whether two maps are equal. I can't just use map1.equals(map2) because even if they have all the same keys and values, they might be in a different order. So I wanted to go througheach key in the first map and get its value and compare it to the value for that key in the second map. And I wanted to do it generically. So I wrote this (which is sort of a stub to demonstrate my question. I will do more null checking, etc):

public void assertMapEquals( Map<Object, Object> f, Map<Object, Object> l) {

    // This will do null checks, don't worry
    for ( Entry<Object, Object> ent : f.entrySet()) {       
        if (f.size() != l.size()) {
            throw new AssertionError ("size mismatch");
        }       
        Object k = ent.getKey();
        Object e = ent.getValue();
        Object a = l.get(k);        
        if (!e.equals(a)) {
            throw new AssertionError( "unequal");
        }       
    }
}

Then I try to call it with two String maps:

public static void main(String[] argv) throws SQLException {

    Map<String,String> m1 = new HashMap<>();
    Map<String,String> m2 = new HashMap<>();
    // Data will get filled in later
    assertMapEquals(m1, m2);
    // ...
 }

but Eclipse is giving me the following error on the call:

The method assertMapEquals(Map, Map) in the type MyMain1 is not applicable for the arguments (Map, Map)

Aren't strings objects, so why won't this work, and what should I do? This question can apply to any example of this sort, not just comparing two maps.

An additional question I would have is is there a better way I can do this where it compares but does not care about the order?

You may use generic method paramethized by <?, ?> (not <K, V> , because as mentioned in comments they may be of different type and still equal, eg Map<String, String> vs Map<Object, Object> ) :

public static void assertMapEquals(Map<?, ?> f, Map<?, ?> l) {
    if (f == null || l == null)
         throw new NullPointerException();
    if (f.size() != l.size()) 
            throw new AssertionError ("size mismatch");
    for (Entry<?, ?> ent : f.entrySet()) {            
        Object k = ent.getKey();
        Object e = ent.getValue();
        Object a = l.get(k);        
        if (!Objects.equals(e, a))      // handle null values
            throw new AssertionError("unequal");
    }
}

The other approach will be just directly compare maps:

public static void assertMapEquals(Map<?, ?> f, Map<?, ?> l) {
     if (f == null || l == null)
         throw new NullPointerException();
     if (f.size() != l.size())
         throw new AssertionError("size mismatch");
     if (!f.equals(l))
         throw new AssertionError("unequal contents");
}

By contract, Map#equals(Object o) returns true iff o is Map which has equal contents.

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