ArrayList as key in HashMap

前端 未结 9 1842
Happy的楠姐
Happy的楠姐 2020-11-29 09:17

Would it be possible to add an ArrayList as the key of HashMap. I would like to keep the frequency count of bigrams. The bigram is the key and the

相关标签:
9条回答
  • 2020-11-29 09:49

    Why can't you use something like this:

    class Bigram{
        private String firstItem;
        private String secondItem;
    
        <getters/setters>
    
        @Override
        public int hashCode(){
            ...
        }
    
        @Override 
        public boolean equals(){
            ...
        }
    }
    

    instead of using the dynamic collection for limited number of items (two).

    0 讨论(0)
  • 2020-11-29 09:54

    Sure it possible. I suppose the issue in your put. Try obtain key for bigram, increment it, remove entry with this bigram and insert updated value

    0 讨论(0)
  • 2020-11-29 09:55

    Please check below my code in order to understand if key is ArrayList in Map and how JVM will do it for inputs: here i write hashCode and equals method for TesthashCodeEquals class.

    package com.msq;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    class TesthashCodeEquals {
        private int a;
        private int b;
    
        public TesthashCodeEquals() {
            // TODO Auto-generated constructor stub
        }
    
    
    
        public TesthashCodeEquals(int a, int b) {
            super();
            this.a = a;
            this.b = b;
        }
    
    
    
        public int getA() {
            return a;
        }
    
        public void setA(int a) {
            this.a = a;
        }
    
        public int getB() {
            return b;
        }
    
        public void setB(int b) {
            this.b = b;
        }
    
        public int hashCode() {
    
            return this.a + this.b;
        }
    
        public boolean equals(Object o) {
    
            if (o instanceof TesthashCodeEquals && o != null) {
    
                TesthashCodeEquals c = (TesthashCodeEquals) o;
    
                return ((this.a == c.a) && (this.b == c.b));
    
            } else
                return false;
        }
    }
    
    public class HasCodeEquals {
        public static void main(String[] args) {
    
            Map<List<TesthashCodeEquals>, String> m = new HashMap<>();
    
            List<TesthashCodeEquals> list1=new ArrayList<>();
            list1.add(new TesthashCodeEquals(1, 2));
            list1.add(new TesthashCodeEquals(3, 4));
    
            List<TesthashCodeEquals> list2=new ArrayList<>();
            list2.add(new TesthashCodeEquals(10, 20));
            list2.add(new TesthashCodeEquals(30, 40));
    
    
            List<TesthashCodeEquals> list3=new ArrayList<>();
            list3.add(new TesthashCodeEquals(1, 2));
            list3.add(new TesthashCodeEquals(3, 4));
    
    
    
            m.put(list1, "List1");
            m.put(list2, "List2");
            m.put(list3, "List3");
    
            for(Map.Entry<List<TesthashCodeEquals>,String> entry:m.entrySet()){
                for(TesthashCodeEquals t:entry.getKey()){
                    System.out.print("value of a: "+t.getA()+", value of b: "+t.getB()+", map value is:"+entry.getValue() );
                    System.out.println();
                }
                System.out.println("######################");
            }
    
        }
    }
    

    .

    output:
    
    value of a: 10, value of b: 20, map value is:List2
    value of a: 30, value of b: 40, map value is:List2
    ######################
    value of a: 1, value of b: 2, map value is:List3
    value of a: 3, value of b: 4, map value is:List3
    ######################
    

    so this will check the number of objects in List and the values of valriabe in object. if number of objects are same and the values of instance variables is also same then it will consider duplicate key and override the key.

    now if i change only the value of object on list3

    list3.add(new TesthashCodeEquals(2, 2));

    then it will print:

     output
        value of a: 2, value of b: 2, map value is:List3
        value of a: 3, value of b: 4, map value is:List3
        ######################
        value of a: 10, value of b: 20, map value is:List2
        value of a: 30, value of b: 40, map value is:List2
        ######################
        value of a: 1, value of b: 2, map value is:List1
        value of a: 3, value of b: 4, map value is:List1
    ######################
    

    so that It always check the number of objects in List and the value of instance variable of object.

    thanks

    0 讨论(0)
  • 2020-11-29 09:57

    Yes you can have ArrayLists as a keys in a hash map, but it is a very bad idea since they are mutable.

    If you change the ArrayList in any way (or any of its elements), the mapping will basically be lost, since the key won't have the same hashCode as it had when it was inserted.

    The rule of thumb is to use only immutable data types as keys in a hash map. As suggested by Alex Stybaev, you probably want to create a Bigram class like this:

    final class Bigram {
    
        private final String word1, word2;
    
        public Bigram(String word1, String word2) {
            this.word1 = word1;
            this.word2 = word2;
        }
    
        public String getWord1() {
            return word1;
        }
    
        public String getWord2() {
            return word2;
        }
    
        @Override
        public int hashCode() {
            return word1.hashCode() ^ word2.hashCode();
        }
    
        @Override
        public boolean equals(Object obj) {
            return (obj instanceof Bigram) && ((Bigram) obj).word1.equals(word1)
                                           && ((Bigram) obj).word2.equals(word2);
        }
    }
    
    0 讨论(0)
  • 2020-11-29 09:57

    I've come up with this solution. It is obviously not usable in all cases, for example over stepping the hashcodes int capacity, or list.clone() complications(if the input list gets changed, key stays the same as intended, but when the items of List are mutable, cloned list has the same reference to its items, which would result in changing the key itself).

    import java.util.ArrayList;
    
    public class ListKey<T> {
        private ArrayList<T> list;
    
        public ListKey(ArrayList<T> list) {
            this.list = (ArrayList<T>) list.clone();
        }
    
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
    
            for (int i = 0; i < this.list.size(); i++) {
                T item = this.list.get(i);
                result = prime * result + ((item == null) ? 0 : item.hashCode());
            }
            return result;
        }
    
        @Override
        public boolean equals(Object obj) {
            return this.list.equals(obj);
        }
    }
    
    ---------
        public static void main(String[] args) {
    
            ArrayList<Float> createFloatList = createFloatList();
            ArrayList<Float> createFloatList2 = createFloatList();
    
            Hashtable<ListKey<Float>, String> table = new Hashtable<>();
            table.put(new ListKey(createFloatList2), "IT WORKS!");
            System.out.println(table.get(createFloatList2));
            createFloatList2.add(1f);
            System.out.println(table.get(createFloatList2));
            createFloatList2.remove(3);
            System.out.println(table.get(createFloatList2));
        }
    
        public static ArrayList<Float> createFloatList() {
            ArrayList<Float> floatee = new ArrayList<>();
            floatee.add(34.234f);
            floatee.add(new Float(33));
            floatee.add(null);
    
            return floatee;
        }
    
    Output:
    IT WORKS!
    null
    IT WORKS!
    
    0 讨论(0)
  • 2020-11-29 09:58

    Try this ,this will work.

     public Map<List, Integer> getBigramMap (String word1,String word2){
        Map<List,Integer> hm = new HashMap<List, Integer>();
        List<String> arrList1 = new ArrayList<String>();
        arrList1 = getBigram(word1, word2);     
        if(hm.get(arrList1) !=null){
            hm.put(arrList1, hm.get(arrList1)+1);
        }
        else {
            hm.put(arrList1, 1);
        }
    
        System.out.println(hm.get(arrList1));
        return hm;
    }
    
    0 讨论(0)
提交回复
热议问题