Void Class in HashMap as a Value object - java

I know the basic that a HasMap is a Key-Value pair but I want to have a HashMap with keys only(No Values)
I want to put below java snippet in my complex method(i.e HashMap with only Keys and no value associated to those Keys). My requirement is that i am processing a List of Duplicate Records, and during comparisons, I am keeping only one identifier value(from group of duplicates) in a HasMap which I can later compare that whether the system has already processed it or not.
Here is the code snippet(gives Compile time error as Void class is uninstantiable).
Map<Integer,Void> map=new HashMap<Integer, Void>();
//Some Logic goes here
map.put("ss",new Void());
Any suggestion/help to have a HasMap only Keys with no value are welcome.

Normally you would use a Set for such an issue, because there is no need to have a Key-Value structure when not using the value at all.
Correct Solution
Set<String> uniqueValues = new HashSet<String>();
uniqueValues.add( "a" );
uniqueValues.add( "a" );
assert uniqueValues.size() == 1;
Note this is just for completeness I would always use a Set for your requirement and the rest is more for fun/learning/confuse people:
Since Void has a private constructor so you can not create an instance with the new Keyword.
However there are at least two possibilities to put something in your Map.
Solution one is to add null as value. Because you do not need it anyway. And the second one would use reflection to ignore the private constructor of the Void class.
HACK SOLUTION
Map<String, Void> map = new HashMap<String,Void>();
Constructor<Void> constructor= (Constructor<Void>) Void.class.getDeclaredConstructors()[0];
constructor.setAccessible(true);
Void voidObj = constructor.newInstance();
map.put( "a", voidObj );
map.put( "a", voidObj );
assert map.size() == 1;

If I understand correctly you want a list where you can add keys but it should not allow to add duplicate keys. Then the solution is to use a Set(Oracle Documentation):
Set<Integer> mySet = new TreeSet<Integer>();
Java also provides a Hashset(Oracle Documentation)
Set<Integer> mySet = new HashSet<Integer>();
You may also need you own Comparator.

Why not just use another list? If you really need to use a HashMap for whatever reason, you can just add null values instead of void.
Map<Integer,Object> map=new HashMap<Integer, Object>();
map.put("ss", null);

Please do not do this. A HashMap is a Map which is a Key-Value-pair. A Map without values is not a Map.
If you want to store values without duplicates use a Set - a HashSet for example.

First of all the constructor of Void class is private, so the compiler will mark new Void() as error. Next, to prevent duplicates, you could just use a Set . Why not go with HashSet?.
Here's what javadoc says about Void -->
The Void class is an uninstantiable placeholder class to hold a
reference to the Class object representing the Java keyword void.

Related

Compare two HashMaps keys for equality?

I have two HashMap<HashSet<String>, Long> that I want to compare based on the Key. The Key is a HashSet<String>, I might need to change to TreeSet<String> but I don't think it is necessary. How would I compare these?
NOTE: The Map is just used as a wrapper around a single Set.
for(HashMap<HashSet<String>, Long> entry : ListOfMaps) {
if(entry.keySet().equals(entry2.keySet())) {
// do something
}
}
I want to check the Set1.equals(Set2).
The set must be exactly the same. Since there is only one Set<String> in each HashMap<Set<String>, Long> it makes me nervous that I am grabbing all the Keys, or is this okay?
The equals() contract of Set says:
Returns true if the given object is also a set, the two sets have the same size, and every member of the given set is contained in this set. This ensures that the equals method works properly across different implementations of the Set interface.
So your code will work as long as the Set implementation follows the contract.
However, this may be dangerous depending on what your code does with the Sets that are used as keys. Once an object is used as a key in a Map, it shouldn't change because that breaks the contract of Map.
Map<Set<String>, T> map = HashMap<>();
Set<String> mySet = new HashSet<>();
mySet.add("first");
map.put(mySet, myValue);
Set<String> copyOfMySet = new HashSet<>(mySet);
//returns true
map.contains(copyOfMySet);
//modifying mySet
mySet.remove("first");
//this will now return false
map.contains(copyOfMySet);

How to use hashmap.put without overriding the previous data? (java)

I have something along the lines of this:
public HashMap<Boolean, String> map = new HashMap();
map.put(this.inverted, "Inverted");
map.put(this.active, "Loading");
System.out.println(map.size());
after seeing that the size was always 1, I realised that using map.put was overriding the previous data. I am currently trying to iterate over the hashmap. Is there a way to add mappings to it without overriding previous ones?
You have declared your HashMap as: -
public HashMap<Boolean, String> map = new HashMap();
Now, just think how many maximum mapping can you have in your map? The answer you can get by thinking of, what all values can your Boolean type take. This is because, you cannot have duplicate keys in a HashMap.
So, probably you got it now, that you can at max have only 2 mappings in your map, one for true and other for false(In fact you can have a 3rd one too, as you can have a mapping for a null key too in your HashMap).
So, in your case, if both this.inverted and this.active are either true or false. Then only one of them can be there, and that would be the later value inserted.
Is there a way to add mappings to it without overriding previous ones?
Probably you have build your HashMap wrongly. You should declare your map as: -
private Map<String, Boolean> map = new HashMap();
And now you can put two mappings as: -
map.put("Inverted", this.inverted);
map.put("Loading", this.active);
It's because this.inverted.equals(this.active) and this.inverted.hashcode()==this.active.hashcode()
Maybe you need redefine the equals method for the key.
In MAP
An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value. ---> from Map Api
from your implementation, may be this.inverted and this.active both have same value.
Check the input once. print the keySet, then check.
or change the input to Map<String, Boolean>
As #Frank suggest you should invert your Map.
public final Map<String, Boolean> map = new HashMap<>();
map.put("Inverted", this.inverted);
map.put("Loading", this.active);
System.out.println(map);
If the keys are the same than the previous value is overwritten in a standard Java Map. If you don't want this, you can have a look at a multimap which is implemented for example in commons-collections. It can hold different values for one key.
Hashmap is based on key/value pairs. If your keys are equal (they have the same hashcode), it will behave as you described.
For your use case, reversing your key/value pairs will help you.
public HashMap<String, Boolean> map = new HashMap();
map.put("Inverted", this.inverted);
map.put("Loading", this.active);
System.out.println(map.size());
Get object of innermap ,by passing outer map key .. Then check if key of innermap exists then update values with previous data. else create new object of inner map.

Cannot Create an LinkedList<String, int>

i want to create an LinkedList of couple that the key is a String and the value is an integer ?
LinkedList doesn't have a key. It's a list of elements, not a key/value mapping.
If you want a LinkedList where each element is a pair of Integer/String values, you'll need to pick one of:
Create a generic Pair class
(Ab)use an existing generic class (e.g. Map.Entry)
Create a custom class for your specific scenario
I would suggest the last option as the most sensible one - you'll be able to give it appropriate semantics and names according to the real meaning of the string and the integer. Heck, you'll also be able to avoid boxing the integer, as you can have:
public class WhateverYouCallIt {
private final int firstValue;
private final String secondValue;
// Constructor, properties
}
You can only use Object in a LinkedList., this means you cant use Java Primitives.
However, what you seem to need is a Map structure.
I recommend using java.util.HashMap, it allows you to create a Key, Value pairs.
Example:
HashMap<String,Integer> a = new HashMap<String,Integer>();
a.put("one",1);
a.put("two",2);
System.out.println(a.get("one"));
//prints 1
System.out.println(a.get("two"));
//prints 2
EDIT:
As per your comment, i see you required order, use the following example then:
LinkedHashMap<String, Integer> b = new LinkedHashMap<String,Integer>();
b.put("one",1);
b.put("two",2);
b.put("a",3);
for (String key:b.keySet())
{
System.out.println(b.get(key)); // print 1 then 2 finally 3
}
Hope this is what you were asking (if so, modify your question).
One error is you need Integer instead of int, but as others have pointed out LinkedList doesn't take Key/Value pairs.
I'd imagine a HashMap is what your after. As other have stated, you cannot use a primitive type such as "int" in a library storage class like LinkedList, or ArrayList, you must instead use an object such as "Integer".
HashMap hash = new HashMap();
Read this for more information: http://docs.oracle.com/javase/1.4.2/docs/api/java/util/HashMap.html

Java: Using a hashmap, retrieving all values and calling methods

I have a need to store a list of dynamically created objects in a way where they can all be retrieved and their methods called on demand.
As far as I can see for the list and creation, a HashMap fits my needs but i'm a bit puzzled on recalling the objects and calling their methods using the HashMap.
Just as a reference, let me give you a little code:
Here is the HashMap:
Map<String, Object> unitMap = new HashMap<String, Object>();
// here is how I put an object in the Map notice i'm passing coordinates to the constructor:
unitMap.put("1", new Worker(240, 240));
unitMap.put("2", new Worker(240, 240));
Now I need to create a method that retrieves every object in the hashmap and call a method from each object. is this possible or can the created objects only be referenced directly. If so, is there another way to call a method of all existing instances of a class dynamically (in other words, on user input)?
Sure. You can do this:
for (Object thing : unitMap.values()) {
// use "thing" here
}
If you need the keys too, you can either get just the keys:
for (String key : unitMap.keySet()) {
// use "key" here
}
or both the keys and values together:
for (Map.Entry<String, Object> entry : unitMap.entrySet()) {
// use "entry.getKey()" and "entry.getValue()"
}
In all the above cases, each entry in the map is traversed one by one. So at the end of the loop, you'll have processed all the entries in the map.
If all of the values in the Map are Worker objects, you should declare your map to be of type Map<String, Worker>. This way, when you pull a value out of the map, it will be typed as a Worker. This way you can call any method declared on Worker as opposed to having to check the type at runtime using instanceof.
If the map holds different values, and you need to keep the value type as Object, it may be advantageous to use an interface to define the method that you want to call for each different object type.
If you do not know what method you want to run on the values until runtime, and the map can hold different values, you will just have to do what you are currently doing, and use Map<String, Object>.
Finally, to get the values of the map, you do just as Chris Jester-Young mentioned before me. The biggest advantage, as I said previously, is that your objects will be typed, and you will have no need for casting/instanceof checking.
I use this to put all values from hashMap on a List, hope it helps.
private List<String> getValuesFromHashMap(HashMap<String, String> hashMap) {
List<String> values = new ArrayList<String>();
for (String item : hashMap.values()) {
values.add(item);
}
return values;
}

Find a object key from a HashMap

I have a HashMap having key as my own object and key as ArrayList of String. Is there a way to get the key object from the map which is equal to another object without iterating the map. Please note that my object has implemented equals & hashcode. And it only uses 2 attribute of the class to compare. The another object which I am trying to find in the keys of the map has those 2 attribute equal but the other attributes may be different in the key of the map.
//The actual map
private HashMap<FileDetail, ArrayList<String>> map = new HashMap<FileDetail, ArrayList<String>>();
//object to search in above map without iteration.
FileDetail file = some object;
I want to get the reference of the "file" object in the keys of the map.
No you can't do that. HashMap are supposed to work the other way : you have the key, you're looking for the object.
If you have an object and you want to find the key, there's probably something wrong in your logic and your looking in a wrong direction to solve your problem.
If you don't want to iterate over the keySet, then you can use Guava's BiMap. A biMap has an inverse view which is another bimap containing reversed keys and values. This is how you would use it:
BiMap<FileDetail, ArrayList<String>> biMap = HashBiMap.create();
//object to search in above map without iteration.
FileDetail file = some object;
FileDetail key = biMap.inverse().get(biMap.get(file));
If you really need to do this without iteration over the keySet (e.g. because the map is very large), I suggest storing both the key and the list as values in the map. Either create some specific class encapsulating both, or use a simple pair class. The map would look like:
Map<FileDetail, Pair<FileDetail, List<String>>>
If you can't change the type of the map, you can use a second Map<FileDetail, FileDetail> where key and value are always the same objects.
This question is five years old, but I had the same question just today, and found this page. I thought I'd share the solution I decided upon using, which is not described in any of the existing answers and avoids iterating over all the keys in the map. (Please be gentle; this is my first posting on SO. It's tough finding questions I can answer that don't already have answers. Moreover, every question I've had to date has already been asked on SO. I've been using SO for years, with no ability to comment or vote on answers.)
As has been stated already, maps are designed so that when you have a key, you look up a value. That being the case, the answer is to use the key also as the value, so that when you perform a lookup using an arbitrary key, which equals your original key but is not necessarily == to it, you get back the original key. The issue then, is how to get what you originally intended to be the value.
My solution depends on having control of the class used for the key, and control of the map, with the ability to redefine them, which appears to be the case for the OP. In the OP's example, this would be control of the FileDetail class and of the private map variable. Assuming such control, the FileDetail class would be modified to contain a member variable of type ArrayList<String>, which for my sample code below I'll call list, with associated setter and getter methods. For the private map variable, it would be defined thusly:
private HashMap<FileDetail, FileDetail> map = new HashMap<>();
Now, when you want to put a new ArrayList<String> object in the map, assigned to a specific FileDetail key, you assign the ArrayList<String> object to the FileDetail's ArrayList<String> member variable instead, and then place the FileDetail object in the map.
public void putInMap(FileDetail fd, ArrayList<String> al) {
// Ignoring null conditions for simplicity...
fd.setList(al);
map.put(fd, fd);
}
Later, when you get some arbitrary FileDetail object (one that equals the key but isn't necessarily == to it), and you want the associated key, it's a matter of doing a normal lookup:
FileDetail otherFd = getArbitraryFileDetail();
FileDetail originalKeyFd = map.get(otherFd);
And to get the associated ArrayList<String> after having performed the above:
ArrayList<String> al = originalKeyFd.getList();
Certainly this all hinges on the implementations of the equals and hashCode methods of the FileDetail class, but the OP already had those methods defined as desired.
Hope this helps anyone who, like me, comes to this page with a similar situation.
You are likely looking for a Bidirectional Map, Apache Commons Collections includes this as part of the library (im sure there are other imeplementations as well.) A bidirectional map, just as the name implies, is a map but written so as to make looking up by key or by value efficient.
In Java, HashMap associates a key with a value, not the other way around.
You can retrieve a Set of all of the keys using HashMap.keySet(), or alternatively iterate over all of the entries using HashMap.entrySet():
for (Entry <FileDetail, ArrayList<String>> entry : map.entrySet()) {
FileDetail key = entry.getKey();
if (shouldProcess(key)) {
ArrayList<String> list = entry.getValue();
processList(list);
}
}
We get the key object from Hashmap without iterating the keyset of HashMap by converting keyset to ArrayList. This is a simple example:
//Creating hashmap
HashMap<String, String> map = new HashMap<String, String>();
//Adding elements into the map
map.put("1", "Amit");
map.put("2", "Ananth");
map.put("3", "Sunil");
//Get the list from keyset
ArrayList myKeyList = new ArrayList(map.keySet());
//object to search in above map without iteration.
String myobj = "3";
System.out.println(myKeyList.get(myKeyList.indexOf(myobj)));

Categories

Resources