简体   繁体   中英

Java - List sorting doesn't work

I'm trying to sort a hashmap's by sorting it's keys but it doesn't work. The sorting criteria is given by the length of a list that is the hashmap's value. See code below with some unit test.

Class:

package com.fabri.interpreter.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

import com.fabri.interpreter.VerbExpr;
import com.fabri.interpreter.ObjectExpr;

public class Environment {

    private HashMap<VerbExpr, List<ObjectExpr>> map = new HashMap<VerbExpr, List<ObjectExpr>>();

    public List<ObjectExpr> eval(VerbExpr verb) {
        return map.get(verb);
    }

    public void put(VerbExpr verb, ObjectExpr words) {
        List<ObjectExpr> values;
        if(map.get(verb) == null) 
            values = new ArrayList<ObjectExpr>();
        else
            values = map.get(verb);
        values.add(words);
        map.put(verb, values);
    }

    public HashMap<VerbExpr, List<ObjectExpr>> getMap() {
        return map;
    }

    public void sort() {
        List<VerbExpr> keys = new ArrayList<VerbExpr>(map.keySet());
        Collections.sort(keys, new Comparator<VerbExpr>() {
            @Override
            public int compare(VerbExpr verb1, VerbExpr verb2) {
                return map.get(verb1).size()-map.get(verb2).size();
            }
        });
        HashMap<VerbExpr, List<ObjectExpr>> sortedMap = new HashMap<VerbExpr, List<ObjectExpr>>();
        for(VerbExpr verb : keys) {
            sortedMap.put(verb, map.get(verb));
        }
        map = sortedMap;
    }

}

Testing class:

package com.fabri.interpreter.util;

import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.List;

import org.junit.Before;
import org.junit.Test;

import com.fabri.interpreter.ObjectExpr;
import com.fabri.interpreter.VerbExpr;
import com.fabri.interpreter.WordExpr;

public class TestEnvironment {

    private Object[] verbExprs;

    @Before
    public void setUp() {
        Environment env = new Environment();
        List<WordExpr> words1 = new ArrayList<WordExpr>();
        words1.add(new WordExpr("american"));
        words1.add(new WordExpr("italian"));
        env.put(new VerbExpr("was"), new ObjectExpr(words1));
        List<WordExpr> words2 = new ArrayList<WordExpr>();
        words2.add(new WordExpr("zero"));
        words2.add(new WordExpr("one"));
        words2.add(new WordExpr("two"));
        env.put(new VerbExpr("is"), new ObjectExpr(words2));
        env.sort();
        verbExprs = env.getMap().keySet().toArray();
    }

    @Test
    public void testEnvironment() {
        assertTrue(((VerbExpr)verbExprs[0]).equals("is"));
        assertTrue(((VerbExpr)verbExprs[1]).equals("was"));
    }

}

Plain hashmaps are inherently unordered. You can't sort them, or assume anything about the order in which the entries are retrieved when iterating over them. Options:

  • Use a TreeMap if you want to sort by key.
  • Use a LinkedHashMap if you want to preserve insertion order (which is what your sort method looks like it assumes)
  • Create a list of key/value pairs and sort that instead.

正如jon所说,我建议保留一个有序的密钥列表,并使用它来访问固有的无序哈希映射。

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