I have a below program, My enum has value "2" but it just doesn't work the way it is expected. Any help will be appreciated.
package com.deepak.streams;
import com.google.common.collect.ImmutableMap;
import java.util.HashMap;
import java.util.Map;
public class Demo2 {
public static void main(String[] args) {
if (Scores.scoreMap.containsKey("2")) {
System.out.println("Contains Value");
} else {
System.out.println("Does not contains Value");
}
}
public enum Scores {
PASS(1), FAIL(2), MATRIC(3), PROMOTED(4);
private Integer alias;
private static final Map<Object, Scores> scoreMap;
Scores(Integer iAlias) {
alias = iAlias;
}
static {
final Map<Object, Scores> tmpMap = new HashMap<Object, Scores>();
for(final Scores scores : Scores.values()) {
tmpMap.put(scores.alias, scores);
tmpMap.put(scores.name(), scores);
}
scoreMap = ImmutableMap.copyOf(tmpMap);
}
public Integer getAlias() {
return alias;
}
public static Scores getStudentScoreEnum(Integer intVal) {
return getScores(intVal);
}
public static Scores getStudentScoreEnum(String strVal) {
return getScores(strVal);
}
private static Scores getScores(Object objVal) {
if(null != objVal && !scoreMap.containsKey(objVal)) {
throw new IllegalArgumentException("Unknown Value: " + objVal);
}
return scoreMap.get(objVal);
}
}
}
Your map key is an Object:
final Map<Object, Scores> tmpMap = new HashMap<Object, Scores>();
This means it can be any Java Object. When you use put twice:
tmpMap.put(scores.alias, scores);
tmpMap.put(scores.name(), scores);
your map will now contain two new keys. The first one is an Integer since the argument, scores.alias, is an Integer. The second one is a String.
When you perform a lookup on "2", it won't find the Integer key, because "2" is a String, and "2".equals(x) is false for any x that isn't a String. Put simply, the string "2" does not equal the Integer 2.
If you really want to look up keys using String representations of integers as the key, you'll need to use a String as a key when adding to the map. That is:
tmpMap.put(scores.alias.toString(), scores);
Your best bet is to declare the map as having a String key, instead of Object, so that problems like this will be caught at compile time--unless you really want to be able to use both Integer and String values to do your lookups.
Your map contains a binding for the integer 2, not the string "2". The name mapping will be "MATRIC" -> enumValue.
Related
I want to implement a function in java that gets string input and process it. Here is how i implement it using if else statement:
class Main {
static String string_process(String s_in) {
String s_out;
if(s_in.contains("USA")){
s_out = "english";
}
else if(s_in.contains("Germany")){
s_out = "dutch";
}
else if(s_in.contains("Brazil")){
s_out = "Portuguese";
}
else {
s_out = "Uknown";
}
return s_out;
}
public static void main(String[] args) {
String process = string_process("I am from USA!");
System.out.println("I understand "+process);
}
}
I'm wondering if i can implement it hashmap. Is there any benefit of doing so in terms of complexity?
The benefit is that it requires less code to handle the cases and to add a new case.
This is what it looks like with a map:
class Main {
static Map<String, String> countryToLanguageMap = Map.of(
"USA", "english",
"Germany", "dutch",
"Brazil", "Portuguese"
);
static String string_process(String s_in) {
for (Map.Entry<String, String> entry : countryToLanguageMap.entrySet()) {
if(s_in.contains(entry.getKey())){
return entry.getValue();
}
}
return "Unknown";
}
public static void main(String[] args) {
String process = string_process("I am from USA!");
System.out.println("I understand "+process);
}
}
For example, let's suppose you want to add a new case, "UK" with "english". This is what you would have to add with the map-based version:
...
"UK", "english",
...
while with the original version:
...
else if(s_in.contains("UK")){
s_out = "english";
}
...
In short it would make the code more readable but it the runtime complexity would not change in a notable capacity. Like the other answers you would need to make a global hash-map variable to hold the key-value pairs.
Here's a possible solution using Stream API and static Map.
Note: names like string_process() are not aligned with Java naming convention and doesn't provide much information to the reader about its purpose.
Basically solution boils down to a combination of methods filter()+findFirst(), which produces an Optianal. In case if optional is empty, default value "Unknown" would be provided as a result.
private static final Map<String, String> COUNTRY_BY_LANGUAGE =
Map.of("USA", "English", "Germany", "German", "Brazil", "Portuguese");
public static String processCountry(String from) {
return COUNTRY_BY_LANGUAGE.entrySet().stream()
.filter(entry -> entry.getKey().contains(from))
.findFirst()
.map(Map.Entry::getValue)
.orElse("Unknown");
}
Simple brute-force solution without sophisticated algorithms would be:
build your HashMap
Loop through keys in hashMap, using 'indexOf' method of String checking if index >= 0
That would be n*k time complexity (n - keyword count, k - Average input string length)
public class Solution {
private static final Map<String, String> COUNTRY_TO_LANGUAGE = Map.of(
"USA", "English",
"Germany", "Deutsch",
"Brazil", "Portuguese");
private static final String UNKNOWN = "Unknown";
public static String find(String greeting) {
for(String key: COUNTRY_TO_LANGUAGE.keySet()) {
if (greeting.indexOf(key) >= 0) return COUNTRY_TO_LANGUAGE.get(key);
}
return UNKNOWN;
}
public static void main(String[] args) {
String greeting = "I am from USA!";
System.out.println("I understand " + find(greeting));
}
}
So instead of adding new if-else block you just update your map.
I'm having a BiMap with a String as key and an array of Strings as value.
Now i'm trying to get with a single String (which is part of the value array) the key.
private static BiMap<String, String[]> map = ImmutableBiMap.<String, String[]>builder().build();
static {
map.put("000", new String[] {"CH", "CHE", "Switzerland"});
map.put("001", new String[] {"US", "USA", "United States of America"});
map.put("002", new String[] {"IT", "ITA", "Italy"});
}
And in the next method i'm trying to search with "CH" to get "000" (which does not work).
private static String getKey(Map<String,String[]> map, String find) {
Map<String[], String> inversedMap = map.inverse();
if(inversedMap.containsKey() {
return inversedMap.get(find);
}
return null;
}
Is there a way to 'find' the key like this, without that i need to search with an array like this: String[] find = new String[] {"CH", "CHE", "Switzerland"};
All the values and keys are unique, so there is expected only a single result.
And i'm searching always for the first value in the array, f.ex. "CH" or "US".
No, there is no way to find the key like you want. You have to either change the way you store the data to support all the different lookup method you need or go through all keys one by one (at which point making an inverse map makes no sense an you can just go through the Map entries).
A trivial approach would be a purpose built class that contains several maps.
In case you have a case to find smth. by value (not by key) then you could use for loop in case you do not worry about performance. Otherwise, you should wrap this BiMap with a wrapper and add addtional Map with val -> key:
public final class CountryCache {
private final Map<String, String[]> codeNames = new HashMap<>();
private final Map<String, String> nameCode = new HashMap<>();
{
codeNames.put("000", new String[] { "CH", "CHE", "Switzerland" });
codeNames.put("001", new String[] { "US", "USA", "United States of America" });
codeNames.put("002", new String[] { "IT", "ITA", "Italy" });
codeNames.forEach((code, names) -> Arrays.stream(names).forEach(name -> nameCode.put(name, code)));
}
private static final CountryCache INSTANCE = new CountryCache();
public static CountryCache getInstance() {
return INSTANCE;
}
private CountryCache() {
}
public String findByName(String name) {
return nameCode.get(name);
}
}
I'm developing a Java Application that reads a lot of strings data likes this:
1 cat (first read)
2 dog
3 fish
4 dog
5 fish
6 dog
7 dog
8 cat
9 horse
...(last read)
I need a way to keep all couple [string, occurrences] in order from last read to first read.
string occurrences
horse 1 (first print)
cat 2
dog 4
fish 2 (last print)
Actually i use two list:
1) List<string> input; where i add all data
In my example:
input.add("cat");
input.add("dog");
input.add("fish");
...
2)List<string> possibilities; where I insert the strings once in this way:
if(possibilities.contains("cat")){
possibilities.remove("cat");
}
possibilities.add("cat");
In this way I've got a sorted list where all possibilities.
I use it like that:
int occurrence;
for(String possible:possibilities){
occurrence = Collections.frequency(input, possible);
System.out.println(possible + " " + occurrence);
}
That trick works good but it's too slow(i've got millions of input)... any help?
(English isn’t my first language, so please excuse any mistakes.)
Use a Map<String, Integer>, as #radoslaw pointed, to keep the insertion sorting use LinkedHashMap and not a TreeMap as described here:
LinkedHashMap keeps the keys in the order they were inserted, while a TreeMap is kept sorted via a Comparator or the natural Comparable ordering of the elements.
Imagine you have all the strings in some array, call it listOfAllStrings, iterate over this array and use the string as key in your map, if it does not exists, put in the map, if it exists, sum 1 to actual result...
Map<String, Integer> results = new LinkedHashMap<String, Integer>();
for (String s : listOfAllStrings) {
if (results.get(s) != null) {
results.put(s, results.get(s) + 1);
} else {
results.put(s, 1);
}
}
Make use of a TreeMap, which will keep ordering on the keys as specified by the compare of your MyStringComparator class handling MyString class which wraps String adding insertion indexes, like this:
// this better be immutable
class MyString {
private MyString() {}
public static MyString valueOf(String s, Long l) { ... }
private String string;
private Long index;
public hashcode(){ return string.hashcode(); }
public boolean equals() { // return rely on string.equals() }
}
class MyStringComparator implements Comparator<MyString> {
public int compare(MyString s1, MyString s2) {
return -s1.getIndex().compareTo(s2.gtIndex());
}
}
Pass the comparator while constructing the map:
Map<MyString,Integer> map = new TreeMap<>(new MyStringComparator());
Then, while parsing your input, do
Long counter = 0;
while (...) {
MyString item = MyString.valueOf(readString, counter++);
if (map.contains(item)) {
map.put(map.get(item)+1);
} else {
map.put(item,1);
}
}
There will be a lot of instantiation because of the immutable class, and the comparator will not be consistent with equals, but it should work.
Disclaimer: this is untested code just to show what I'd do, I'll come back and recheck it when I get my hands on a compiler.
Here is the complete solution for your problem,
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DataDto implements Comparable<DataDto>{
public int count = 0;
public String string;
public long lastSeenTime;
public DataDto(String string) {
this.string = string;
this.lastSeenTime = System.currentTimeMillis();
}
public boolean equals(Object object) {
if(object != null && object instanceof DataDto) {
DataDto temp = (DataDto) object;
if(temp.string != null && temp.string.equals(this.string)) {
return true;
}
}
return false;
}
public int hashcode() {
return string.hashCode();
}
public int compareTo(DataDto o) {
if(o != null) {
return o.lastSeenTime < this.lastSeenTime ? -1 : 1;
}
return 0;
}
public String toString() {
return this.string + " : " + this.count;
}
public static final void main(String[] args) {
String[] listOfAllStrings = {"horse", "cat", "dog", "fish", "cat", "fish", "dog", "cat", "horse", "fish"};
Map<String, DataDto> results = new HashMap<String, DataDto>();
for (String s : listOfAllStrings) {
DataDto dataDto = results.get(s);
if(dataDto != null) {
dataDto.count = dataDto.count + 1;
dataDto.lastSeenTime = System.nanoTime();
} else {
dataDto = new DataDto(s);
results.put(s, dataDto);
}
}
List<DataDto> finalResults = new ArrayList<DataDto>(results.values());
System.out.println(finalResults);
Collections.sort(finalResults);
System.out.println(finalResults);
}
}
Ans
[horse : 1, cat : 2, fish : 2, dog : 1]
[fish : 2, horse : 1, cat : 2, dog : 1]
I think this solution will be suitable for your requirement.
If you know that your data is not going to exceed your memory capacity when you read it all into memory, then the solution is simple - using a LinkedList or a and a LinkedHashMap.
For example, if you use a Linked list:
LinkedList<String> input = new LinkedList();
You then proceed to use input.add() as you did originally. But when the input list is full, you basically use Jordi Castilla's solution - but put the entries in the linked list in reverse order. To do that, you do:
Iterator<String> iter = list.descendingIterator();
LinkedHashMap<String,Integer> map = new LinkedHashMap<>();
while (iter.hasNext()) {
String s = iter.next();
if ( map.containsKey(s)) {
map.put( s, map.get(s) + 1);
} else {
map.put(s, 1);
}
}
Now, the only real difference between his solution and mine is that I'm using list.descendingIterator() which is a method in LinkedList that gives you the entries in backwards order, from "horse" to "cat".
The LinkedHashMap will keep the proper order - whatever was entered first will be printed first, and because we entered things in reverse order, then whatever was read last will be printed first. So if you print your map the result will be:
{horse=1, cat=2, dog=4, fish=2}
If you have a very long file, and you can't load the entire list of strings into memory, you had better keep just the map of frequencies. In this case, in order to keep the order of entry, we'll use an object such as this:
private static class Entry implements Comparable<Entry> {
private static long nextOrder = Long.MIN_VALUE;
private String str;
private int frequency = 1;
private long order = nextOrder++;
public Entry(String str) {
this.str = str;
}
public String getString() {
return str;
}
public int getFrequency() {
return frequency;
}
public void updateEntry() {
frequency++;
order = nextOrder++;
}
#Override
public int compareTo(Entry e) {
if ( order > e.order )
return -1;
if ( order < e.order )
return 1;
return 0;
}
#Override
public String toString() {
return String.format( "%s: %d", str, frequency );
}
}
The trick here is that every time you update the entry (add one to the frequency), it also updates the order. But the compareTo() method orders Entry objects from high order (updated/inserted later) to low order (updated/inserted earlier).
Now you can use a simple HashMap<String,Entry> to store the information as you read it (I'm assuming you are reading from some sort of scanner):
Map<String,Entry> m = new HashMap<>();
while ( scanner.hasNextLine() ) {
String str = scanner.nextLine();
Entry entry = m.get(str);
if ( entry == null ) {
entry = new Entry(str);
m.put(str, entry);
} else {
entry.updateEntry();
}
}
Scanner.close();
Now you can sort the values of the entries:
List<Entry> orderedList = new ArrayList<Entry>(m.values());
m = null;
Collections.sort(orderedList);
Running System.out.println(orderedList) will give you:
[horse: 1, cat: 2, dog: 4, fish: 2]
In principle, you could use a TreeMap whose keys contained the "order" stuff, rather than a plain HashMap like this followed by sorting, but I prefer not having either mutable keys in a map, nor changing the keys constantly. Here we are only changing the values as we fill the map, and each key is inserted into the map only once.
What you could do:
Reverse the order of the list using
Collections.reverse(input). This runs in linear time - O(n);
Create a Set from the input list. A Set garantees uniqueness.
To preserve insertion order, you'll need a LinkedHashSet;
Iterate over this set, just as you did above.
Code:
/* I don't know what logic you use to create the input list,
* so I'm using your input example. */
List<String> input = Arrays.asList("cat", "dog", "fish", "dog",
"fish", "dog", "dog", "cat", "horse");
/* by the way, this changes the input list!
* Copy it in case you need to preserve the original input. */
Collections.reverse(input);
Set<String> possibilities = new LinkedHashSet<String>(strings);
for (String s : possibilities) {
System.out.println(s + " " + Collections.frequency(strings, s));
}
Output:
horse 1
cat 2
dog 4
fish 2
This question already has answers here:
How to make HashMap work with Arrays as key?
(9 answers)
Closed 8 years ago.
I am having performance problems due to the fact that in order to retrieve the value for some key, I have to check whether each key stored in the map is equal to my test key. The performance problem stems from the fact that I had to override the map's get operation which checks if the map has the test key. I need some kind of tuples for my keys and I use String[] to store two Strings. Here is my class with a map.
public class ClassWithMap {
Map<String[], Double> arrayToDoubleMap;
public ClassWithMap() {
arrayToDoubleMap = new HashMap<String[], Double>() {
#Override
public Double get(Object key) {
String[] stringArray = (String[]) key;
Set<String[]> keySet = this.keySet();
for (String[] tuple : keySet) {
if (tuple[0].equals(stringArray[0]) && tuple[1].equals(stringArray[1])) {
key = tuple;
break;
}
}
return super.get(key);
}
};
}
public Double getDouble(String string1, String string2) {
String[] tuple = { string1, string2 };
return (Double) arrayToDoubleMap.get(tuple);
}
}
Here is some method for testing.
public static void main(String[] args) {
ClassWithMap map = new ClassWithMap();
String[] tuple1 = { "foo", "bar" };
map.arrayToDoubleMap.put(tuple1, 0.0);
String[] tuple2 = { "fee", "fum" };
map.arrayToDoubleMap.put(tuple2, 1.0);
System.out.println(map.getDouble("fee", "fum"));
}
If I do not override the get operation in the map declaration, I get null because the String[] key is not exactly the same as the test String[] key.
So my question is: is there a more efficient way to impose this object equivalence than to make a method which checks if there is a match between every key and test key?
You should probably create a class to hold the two strings instead of putting them in an array:
class StringPair {
private final String str1, str2;
public StringPair(final String str1, final String str2) {
this.str1 = str1;
this.str2 = str2;
}
public String getStr1() {
return str1;
}
public String getStr2() {
return str2;
}
#Override
public boolean equals(Object o) {
if (!(o instanceof StringPair))
return false;
StringPair sp = (StringPair) o;
return Objects.equals(str1, sp.str1) && Objects.equals(str2, sp.str2);
}
#Override
public int hashCode() {
return Arrays.asList(str1, str2).hashCode();
}
}
Now, you would use a Map<StringPair, Double>.
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 value is its frequency.
For each of the bigrams like "he is", I create an ArrayList for it and insert it into the HashMap. But I am not getting the correct output.
public HashMap<ArrayList<String>, Integer> getBigramMap(String word1, String word2) {
HashMap<ArrayList<String>, Integer> hm = new HashMap<ArrayList<String>, Integer>();
ArrayList<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;
}
public ArrayList<String> getBigram(String word1, String word2) {
ArrayList<String> arrList2 = new ArrayList<String>();
arrList2.add(word1);
arrList2.add(word2);
return arrList2;
}
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);
}
}
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).
From the documentation:
Note: great care must be exercised if mutable objects are used as map
keys. The behavior of a map is not specified if the value of an object is
changed in a manner that affects equals comparisons while the
object is a key in the map. A special case of this prohibition is that it
is not permissible for a map to contain itself as a key. While it is
permissible for a map to contain itself as a value, extreme caution is
advised: the equals and hashCode methods are no longer
well defined on such a map.
You have to take care when you are using mutable objects as keys for the sake of hashCode and equals.
The bottom line is that it is better to use immutable objects as keys.
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;
}
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!
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
Unlike Array, List can be used as the key of a HashMap, but it is not a good idea, since we should always try to use an immutable object as the key.
.toString() method getting the String represtenation is a good key choice in many cases, since String is an immuteable object and can prefectly stands for the array or list.
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
ArrayList.equals() is inherited from java.lang.Object - therefore equals() on ArrayList is independent of the content of the list.
If you want to use an ArrayList as a map key, you will need to override equals() and hashcode() in order to make two arraylists with the same content in the same order return true on a call to equals() and return the same hashcode on a call to hashcode().
Is there any particular reason you have to use an ArrayList as opposed to say a simple String as the key?
edit: Ignore me, as Joachim Sauer pointed out below, I am so wrong it's not even funny.