More Efficient Hash Table [duplicate] - java

This question already has answers here:
Multi-valued hashtable in Java
(13 answers)
Closed 7 years ago.
I'm looking to build a hash table where multiple String keys that share the same Byte array value are merged into one value with multiple keys. This is so the value isn't stored over and over again with different values. Adding a key with a value should also overwrite any existing key with the same name, but keep the value if it has a different key as well, but delete it when there is no other key.
EDIT: How do I build this data structure? For example, if I insert "hello" with a value, then add "World" with the same value, I would like the structure to something along the lines of [[Hello, World], Value] instead of [Hello, Value], [World, Value]. I tried using a list as my hashkey, but found I couldnt recall the value. Here is my code:
HashMap<List<String>, byte[]> map = new HashMap<List<String>, byte[]>();
public void storeByte (String id, int value) {
byte[] byteValue = new byte[value];
ArrayList<String> idlist = new ArrayList<String>();
idlist.add(id);
map.put(idlist, byteValue);
System.out.println(map);
}
public byte[] fetchByte(String id) {
ArrayList<String> idlistsearch = new ArrayList<String>();
idlistsearch.add(id);
byte[] output = map.get(id);
if(map.containsKey(idlistsearch)){
output = map.get(id);
} else {
return null;
}
return output;
I hope this makes sense,
Thank you.

i'm looking to build a hash table where multiple String keys that share the same Byte array value are merged into one value with multiple keys.
This is how HashMap and Hashtable works. There isn't any other option builtin.
When you define
byte[] bytes =
this is a reference, not an actual object. When you add this reference to the map, you are adding this reference and it can be added as many times as you like, but there is only one copy.
if I insert "hello" with a value, then add "World" with the same value,
You can do
byte[] bytes =
map.put("Hello", bytes);
map.put("World", bytes);
This is two keys and only one value.

Related

How to access a single ArrayList in ArrayListMultiMap

I would like to get an entry from ArrayList in an ArrayListMultiMap. I am using Google Guava ArrayListMultimap and each key is associated with multiple array lists. For example, for the key1 I have 4 array lists, and each ArrayList contains 2 entries. I need to be able to access a particular ArrayList and get an entry from there so my question is how do I do it? Every time I try to access the value associated with the key it prints all 4 array lists but I need only one.
Multimap<String, ArrayList<String>> wordAsKey = ArrayListMultimap.create();
for (DictionaryEntries dict : DictionaryEntries.values()) {
ArrayList<String> list = new ArrayList<>();
String key = dict.getKey();
String partOfSpeech = dict.getPartOfSpeech();
String definition = dict.getDefinition();
list.add(partOfSpeech);
list.add(definition);
wordAsKey.put(key, list);
}
ArrayList<String> resultList = new ArrayList<>();
resultList.add(wordAsKey.get(word).toString());
System.out.println(resultList);
Prints
[[[noun, A set of pages.], [noun, A written work published in printed or electronic form.], [verb, To arrange for someone to have a seat on a plane.], [verb, To arrange something on a particular date.]]]
But I need it to print only [noun, A set of pages.]
you can try: get index value
int index = 0;
resultList.add(wordAsKey.get(word).get(index).toString());
Just do it like this -
ArrayList<String> list = (ArrayList<String>)wordAsKey.get(word);
String result = list.get(index);
System.out.println(result);
And you can check whether particular String is exist or not in List, then see below;
if(list.contains("search")){...}

how to get key and how to add more values? [duplicate]

This question already has answers here:
HashMap with multiple values under the same key
(21 answers)
Closed 4 years ago.
public static void main(String[] args) {
// write your code here
LinkedHashMap<String,String>category1=new LinkedHashMap();
category1.put("action","die hard");
Scanner s=new Scanner(System.in);
String answer=s.nextLine();
if (category1.containsKey(answer))
System.out.println(category1.get("action"));
if (category1.containsValue(answer))
System.out.println(category1.keySet());
How to get the key when the user answer with it's specific value, and how to add more values to one key?
1. The map collection, does not support multiple values under the same key, it will override whatever was stored there before.
2. However, you can change it from <String,String> to <String,List<String>>, thus gaining the ability to accumulate the answers from the client into the list. The key will refer to only one object, the list of Strings, but the list itself can hold many values.
3. In order to add more Strings to the list, you will need to retrieve the list by the desired key, and then add your new String to it.
Here is some code that implements the idea:
private void test(){
Map<String, List<String>> categories = new HashMap<>();
String answerFromClient = "Some text";
List<String> actionAnswers = categories.get("action");
if (actionAnswers == null){
actionAnswers = new ArrayList<>();
actionAnswers.add(answerFromClient);
categories.put("action",actionAnswers);
}
else{
actionAnswers.add(answerFromClient);
}
}

hashmap values get changed by doing operations like retainAll() [duplicate]

This question already has answers here:
In Java, what is a shallow copy?
(11 answers)
Closed 4 years ago.
String [] keys0 =a.keySet(). toArray (new String[a.size()]);
Map< String , TreeSet <Integer>> Sub_hash=new HashMap< String, TreeSet <Integer>>();
for(ko = 0 ; ko < keys0 . length ; ko ++) {
Set<Integer> so = test.get( keys0[ko] );
System.out.println(""+so);
for(ko1 = ko+1 ; ko1 < keys0.length; ko1++) {
Set<Integer> so1 = test.get( keys0[ko1] );
boolean tr=so1.retainAll(so);
if(tr && so1.size()>=2) {
Sub_hash. put(keys0[ko]+keys0[ko1], (TreeSet<Integer>) so1);
System.out.println(""+Sub_hash.size()+""+Sub_hash);
}
}}
this is my second post and i dont know how to post neatly the requirement is i have a hash map with keys and values where i need to compare with one key in the map with another key in the map and retain the values and put the result in the sub_hash map but the problem is the original values of the map are changing as the values of the map are updated by the method retainAll();
but when the iteration comes to second key the values are changed completely but the comparison goes like this 2-3,2-4,2-5,2-6,2-7...etc but
as the values are changed result is completely erroneous so is there any chance to make it constant like some variable final to the hashmap.
Here's your problem:
Set<Integer> so1 = test.get( keys0[ko1] );
boolean tr=so1.retainAll(so);
You don't want to modify values in test. You want to modify a copy instead:
Set<Integer> so1 = new TreeSet<>(test.get( keys0[ko1] ));
boolean tr=so1.retainAll(so);
A Map (or any collection) can only contain references to objects, not the objects themselves. When you put a copy of a reference into a collection or get a reference from a collection, you are copying just the reference, not the underlying object.
When you get a set from a Map, and you modify the set, there is only one copy of that set.
NOTE: The Map is not altered when you alter a Set in it.
If you want a copy of a collection, you have to do this explicitly.

Bug in HashMap / ArrayList or wrong code? [duplicate]

This question already has answers here:
ArrayList as key in HashMap
(9 answers)
Closed 6 years ago.
Tired up with trying to resolve the problem with this code:
public class MapTest {
static class T{
static class K{}
}
static Map<List<T.K>, List<String>> map = new HashMap<>();
static List<String> test(List<T.K> list, String s){
List<String> l = map.get(list);
if (l == null){
l = new ArrayList<String>();
System.out.println("New value()");
map.put(list, l);
}
l.add(s);
return l;
}
public static void main(String s[]){
ArrayList<T.K> list = new ArrayList<T.K>();
test(list, "TEST");
list.add(new T.K());
List<String> l = test(list, "TEST1");
System.out.println(l.size());
}
}
It should create a new list-value for the map only once, but output is as follows:
New value
New value
1
it is something wrong happen with hashcode of the list after I insert value in it.
I expect "new value" show up only once, and size will be 2, not 1.
is it just JVM problem or something more general?
mine one is Oracle JVM 1.8.0_65
The hashcode of the list object changes when you put an item in it. You can see how the hashcode is calculated in the ArrayList.hashCode documentation.
In general, using a mutable object as the key for a map isn't going to work well. Per the Map 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.
Thus, when you add the list to the map a second time, the map doesn't see it as being "equal" to the first list (since it isn't according to .equals), so it adds it again.
If you want a map where keys are looked up by identity rather than by value, you can use the IdentityHashMap class.

How to store bytearrays in hashmap or hashtable in java

Hi i have bytearrays of size 8 bytes each and i need to store them in a hashmap or hashtable. For example say i have 1000 blocks... then it will store 1st key and value(bytearray) and then when block2 is passed it should check if it is already present in hahtable and if not there it should increment and count should be incremented. I have written code to store but the problem is that it is not able to search, may be bacuse of the way i'm storing in byte array.
Code:
int collisions = 0;
Hashtable<Integer, Long> ht = new Hashtable<Integer, Long>();
// Given bloc1 value here
if(ht.contains(bloc1)) {
collisions++;
}
else {
ht.put(i,ByteBuffer.wrap(bloc1).getLong());
}
Problem is: ht.contains is not giving the desired o/p
byte[] objects, and other array objects in Java has equals() method inherited from Object, i. e. comparing by reference, not by array contents.
The simpliest way to resolve your problem (without additional dependencies to libraries) is to store 8-byte arrays as longs:
Map<Long, Value> map = new HashMap<>();
...
// map.put(byteArray, value);
map.put(ByteBuffer.wrap(byteArray).getLong(), value);
Solution:
int collisions = 0;
Hashtable ht = new Hashtable();
// Given bloc1 value here
if(ht.contains(ByteBuffer.wrap(bloc1).getLong()))
{collisions++;}
else {
ht.put(i,ByteBuffer.wrap(bloc1).getLong());
}

Categories