how i can get the Key from my Value?
My HashMap:
public static final Map<String, List<String>> Server = new HashMap<>();
my attempt:
public static Object getKeyFromValue(String value) {
for (Object o : Server.keySet()) {
if (Server.get(o).equals(value)) {
return o;
}
}
return null;
}
It dosent work, because the Value is a List.
Use List#contains:
if (Server.get(o).contains(value)) {
//...
}
When you iterate over a Map, if you need both the key and the value it's better to iterate over the entrySet rather than the keySet.
public static String getKeyFromValue(String value) {
for (Map.Entry<String, List<String>> e : Server.entrySet()) {
if (e.getValue().contains(value)) {
return e.getKey();
}
}
return null;
}
This should work, but there are 3 things I don't like about it (apart from Server beginning with a capital letter).
contains for many List implementations (including ArrayList and LinkedList) is slow, because it is a linear search. It may better to use HashSet instead.
If the value occurs in more than one list in the map, the returned key could be any of multiple answers. It may be better for the name of the method to indicate this (e.g. getAnyKeyForValue).
It may be preferable to return an Optional<String> rather than using null to mean that the value was not found.
A Java 8 solution, taking all of these points into consideration and taking advantage of parallelism would be
public static Optional<String> getAnyKeyForValue(String value) {
return Server.entrySet()
.parallelStream()
.filter(e->e.getValue().contains(value))
.map(Map.Entry::getKey)
.findAny();
}
Just changing from equals to contains works. and all remains same
public static Object getKeyFromValue(String value) {
for (Object o : Server.keySet()) {
if (Server.get(o).contains(value)) {
return o;
}
}
return null;
}
Related
I am seaching for a data structure that is almost exactly a HashMap<String,Integer>, but the problem with HashMaps is that most of the data stored in key value pairs is lost by calling the putAll() method on two HashMaps, due to the replacement behavior of putVal() in line 655 of the java/util/HashMap.java.
This is basically the change that I want:
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
-- e.value = value;
++ e.value = value + oldValue;
afterNodeAccess(e);
return oldValue;
}
Is there an existing data structure, that I've overlooked that would do such a thing, or how do I create a class that is basically a HashMap with that one change?
I've already tried to code something, but doen't work how I want it to... In fact it doen't matter if I set the put method on #Override, do it like that, or delete it completely - the replacing behavior ofcourse stays the same, because putAll() uses putVal() that I can't reach / change from the outside - or I at least don't know how...
/**
* doesn't work, putAll() uses putVal() that I can't reach
*/
public class SumHashMap<K> extends HashMap<K, Integer> {
private static final long serialVersionUID = 1L;
public Integer put(K key, Integer value) {
Integer oldValue = get(key);
if (oldValue == null)
return super.put(key, value);
return super.put(key, oldValue + value);
}
}
Thanks in advance
Additional info:
I want to use the putAll() function in the reduction of a stream out of custom HashMaps.
If I have two custom HashMaps of this sort {"key1" : 2, "key3" : 4} and {"key3" : 1} the result of a.putAll(b) should be {"key1" : 2, "key3" : 5}
You don't need a new data structure for this, you don't even need a new class that inherits from HashMap. Instead, use the Map.merge method:
newMap.forEach((k, v) -> oldMap.merge(k, v, Integer::sum));
This code uses Map.forEach to traverse the entries of the new map (the one you'd receive as an argument in putAll) and uses Map.merge (along with Integer::sum) to merge its entries into an already existing map (which I've named oldMap here).
I think this is what you are looking for. I made it so that the key can be any type. If you want, you can remove the generic for the key and just extend HashMap<String, Integer>.
import java.util.HashMap;
import java.util.Map;
public class AddingHashMap<K> extends HashMap<K, Integer> {
#Override
public Integer put(K key, Integer value) {
Integer existingValue = super.get(key);
if (existingValue == null) {
existingValue = value;
} else {
existingValue = existingValue.intValue() + value.intValue();
}
return super.put(key, existingValue);
}
#Override
public void putAll(Map<? extends K, ? extends Integer> m) {
m.entrySet().forEach(entry -> {
this.put(entry.getKey(), entry.getValue());
});
}
}
Here is it working:
public static void main(String[] argv) {
AddingHashMap<String> myAddingHashMap = new AddingHashMap<>();
myAddingHashMap.put("One", 1);
myAddingHashMap.put("Two", 2);
myAddingHashMap.put("One", 3);
myAddingHashMap.entrySet().forEach(entry -> System.out.println(entry.getKey() + " - " + entry.getValue()));
}
Outputs:
One - 4
Two - 2
Later edit: Keep in mind that this is NOT thread-safe.
I don't think there is a datastructure that does that. The purpose of the datastructure is to store data, not to have logic associated to it. The HashMap can store key-value pairs for you but if you need some more advanced, or specific, logic associated with certain operations, you'll need to add it yourself.
One way is to wrap the map in a class which has this logic. Another might be to implenent the Map interface yourself (which could also use a HashMap internally) though I would not recommend that since changing the behaviour is not a great idea.
A minimal wrapper providing adding functionality:
public class AddingMap {
private final HashMap<String, Integer> map;
public AddingMap() {
map = new HashMap<>();
}
public void add(String key, Integer value) {
map.put(key, map.getOrDefault(key, 0) + value);
}
public Integer get(String key) {
return map.get(key);
}
}
Edit
Shouldn't have finished writing the answer half way...
Indeed, the addAll() method is missing:
public void addAll(Map<String, Integer> map) {
map.entrySet().forEach(e -> this.add(e.getKey(), e.getValue()));
}
Given i want to filter a List of Key-Value objects.
My (Document)-Object from the example below looks like this
{
"attributeEntityList" : [
{key: 'key1', value: 'somevalue1'},
{key: 'key2', value: 'somevalue2'},
{key: 'key3', value: 'somevalue3'}
]
}
When I pass in a list of the following keys ["key1", "key2", "key3"], I expect my function to return the whole given List of attributes.
When I pass in a list of the following keys ["key1", "key2"], I expect my function to return a list of Attributes with the given key-names.
When I pass in a list of the following keys ["key1", "key2", "faultyKey"], I expect my function to return an Empty list.
My imperative-style solution looks like this and it works okay:
private List<AttributeEntity> getAttributeEntities(List<String> keys, Document value) {
final List<AttributeEntity> documentAttributeList = value.getAttributeEntityList();
final List<AttributeEntity> resultList = new ArrayList<>();
for(String configKey: keys){
boolean keyInAttribute = false;
for(AttributeEntity documentAttribute : documentAttributeList){
if(configKey.equals(documentAttribute.getAttribute_key())){
keyInAttribute = true;
resultList.add(documentAttribute);
break;
}
}
if(!keyInAttribute){
resultList.clear();
break;
}
}
return resultList;
}
For education and fun (and maybe better scaling) I'd like to know how to convert this piece of Code into a solution using the new Java 8 streaming-api.
This is what I came up with, converting my pre-Java8-code to Java8.
To my eyes it looks much more concise and it's shorter. But it does not, what I expect it to do :/
I'm realy struggling implementing the third bulletpoint of my requirements.
It always returns all (found) Attributes, even when i pass in a not existant key.
private List<AttributeEntity> getAttributeEntities(List<String> keys, Document value) {
final List<AttributeEntity> documentAttributeList = value.getAttributeList();
return documentAttributeList.stream()
.filter(attribute ->
keys.contains(attribute.getAttribute_key())
).collect(Collectors.toList());
}
I'm thinking of implementing my own custom Collector.
Since my Collector should only return the List, when the collected results contain each given key at least once.
Any other Idea on how to achieve that?
This solution passes my tests.
But it feel's like i'm putting the cart before the horse.
It's neither concise nor short or elegant any more.
private List<AttributeEntity> getAttributeEntities(List<String> keys, Document value) {
final List<AttributeEntity> documentAttributeList = value.getAttributeList();
return documentAttributeList.stream()
.filter(attribute ->
keys.contains(attribute.getAttribute_key())
)
.collect(Collectors.collectingAndThen(Collectors.toList(), new Function<List<AttributeEntity>, List<AttributeEntity>>() {
#Override
public List<AttributeEntity> apply(List<AttributeEntity> o) {
System.out.println("in finisher code");
if (keys.stream().allMatch(key -> {
return o.stream().filter(attrbiute -> attrbiute.getAttribute_key().equals(key)).findAny().isPresent();
})) {
return o;
} else {
return new ArrayList<AttributeEntity>();
}
}
}));
}
First of all I must say that I'm also new at Java 8 features, so I'm not familiar with everything, and not very used to functional programming. I tried a different approach, dividing it all into some methods.
Here it is:
public class Main {
private static List<AttributeEntity> documentAttributeList;
static {
documentAttributeList = new ArrayList<>();
documentAttributeList.add(new AttributeEntity("key1", "value1"));
documentAttributeList.add(new AttributeEntity("key2", "value2"));
documentAttributeList.add(new AttributeEntity("key3", "value3"));
}
public static void main(String[] args) {
Main main = new Main();
List<AttributeEntity> attributeEntities = main.getAttributeEntities(Arrays.asList("key1", "key2"));
for (AttributeEntity attributeEntity : attributeEntities) {
System.out.println(attributeEntity.getKey());
}
}
private List<AttributeEntity> getAttributeEntities(List<String> keys) {
if(hasInvalidKey(keys)){
return new ArrayList<>();
} else {
return documentAttributeList.stream().filter(attribute -> keys.contains(attribute.getKey())).collect(toList());
}
}
private boolean hasInvalidKey(List<String> keys) {
List<String> attributeKeys = getAttributeKeys();
return keys.stream().anyMatch(key -> !attributeKeys.contains(key));
}
private List<String> getAttributeKeys() {
return documentAttributeList.stream().map(attribute -> attribute.getKey()).collect(toList());
}
}
If a document can never have multiple attributes with the same name, I think you can do it like this (don't have a compiler handy to try):
Map<String, AttributeEntity> filteredMap=value.getAttributeEntityList().stream()
.filter(at->keys.contains(at.getKey()))
.collect(toMap(at->at.getKey(), at->at));
return filteredMap.keySet().containsAll(keys)
? new ArrayList<>(filteredMap.values())
: new ArrayList<>();
If multiple attributes per name are allowed, you would have to use groupingBy instead of toMap. You can, of course, rewrite this with collectingAndThen but I think it would be less clear.
I came up with something.
I don't know if it it the most elegant solution but at least it works and i can reason about it.
private List<AttributeEntity> getAttributeEntities(List<String> keys, Document value) {
final List<AttributeEntity> documentAttributeList = value.getAttributeList();
boolean allKeysPresentInAnyAttribute = keys.stream()
.allMatch(key ->
documentAttributeList.stream()
.filter(attrbiute ->
attrbiute.getAttribute_key().equals(key)
)
.findAny()
.isPresent()
);
if (allKeysPresentInAnyAttribute) {
return documentAttributeList.stream()
.filter(attribute ->
keys.contains(attribute.getAttribute_key())
)
.collect(Collectors.toList());
}
return new ArrayList<>();
}
Any hints or comments greatly appreciated.
In this problem, I have to have a map with keys and values of strings to see if multiple keys map to the same value. In other words, my method should return true of no two keys map to the same value while false if it does. My attempt to approach this was to put all the maps into a collection and examine each elem to see if there are two copies of the same value; that doesn't seem to be working for me however. Any suggestions will be appreciated, thanks.
The prompt:
Write a method isUnique that accepts a Map from strings to strings as a parameter and returns true if no two keys map to the same value (and false if any two or more keys do map to the same value). For example, calling your method on the following map would return true:
{Marty=Stepp, Stuart=Reges, Jessica=Miller, Amanda=Camp, Hal=Perkins}
Calling it on the following map would return false, because of two mappings for Perkins and Reges:
{Kendrick=Perkins, Stuart=Reges, Jessica=Miller, Bruce=Reges, Hal=Perkins}
The empty map is considered to be unique, so your method should return true if passed an empty map.
My attempt:
public static boolean isUnique(Map<String, String> input) {
Collection<String> values = input.values(); // stores all the values into a collection
for (String names: values) { // goes through each string to see if any duplicates
Iterator<String> wordList = values.iterator(); // iterates words in values collection
int repeat = 0; // counts number of repeats
// goes through each elem to compare to names
if (wordList.hasNext()) {
if (wordList.next().equals(names)) {
repeat++;
}
}
if (repeat > 1) { // if more than one copy of the value exists = multiple keys to same value
return false; // If multiple copies of same value exists
}
}
return true; // all unique values
}
If I understand your question, then I would implement your method generically like so -
public static <K, V> boolean isUnique(Map<K, V> input) {
if (input == null || input.isEmpty()) {
return true;
}
Set<V> set = new HashSet<V>();
for (V value : input.values()) {
set.add(value);
}
return set.size() == input.size();
}
One solution can be during iterating through the Map, you can store the values in Set of Strings. So if the size of original Map and Set is same, then there is no value that maps to two or more Key of Map.
As far as implementation goes, it can be done as follows:
public boolean checkMap(Map<String, String> map) {
Set<String> set = new HashSet<String>();
for(Entry<String, String> entry:map.entrySet()) {
set.add(entry.getValue);
}
if(map.size == set.size)
return true;
return false;
}
The shortest way that I can think of to do this is
public static boolean valuesAreUnique(Map<K,V> input) {
Collection<V> values = input.values();
return (new HashSet<V>(values)).size() == values.size();
}
However, it's not the most performant way of doing this, because as it builds the set, it will keep adding elements even after a duplicate has been found. So it would most likely perform better if you do the following, which takes advantage of the return value from the add method of the Set interface.
public static boolean valuesAreUnique(Map<K,V> input) {
Set<V> target = new HashSet<V>();
for (V value: input.values()) {
boolean added = target.add(value);
if (! added) {
return false;
}
}
return true;
}
Shrikant Kakani's and Elliott Frisch's approach are correct. But, we can make it more efficient by stopping the iteration once we have found a duplicate:
public static boolean isUnique(Map<String, String> input) {
Set<String> uniqueValues = new HashSet<String>();
for (String value : input.values()) {
if (uniqueValues.contains(value)) {
return false;
}
uniqueValues.add(value);
}
return true;
}
The exercises from the book are specific to the chapter, and as far as I understand, it is expected to have a solution per the topic covered. Its understandable that there are multiple and better solutions, which have been submitted above, but the given exercise covers the Map, keys, values, and methods related to them. Using below method stops as soon as the Value is used the second time.
public static boolean isUnique(Map<String, String> map){
Map<String, Integer> check = new HashMap<String, Integer>();
for (String v : map.values()){
if (check.containsKey(v)){
return false;
} else {
check.put(v, 1);
}
}
return true;
}
This is not basically how to sort the HashMap based on keys. For that I could directly use TreeMap without a wink :)
What I have at the moment is
Map<String, Object> favoritesMap = new HashMap<String, Object>();
and its contents can be
["Wednesdays" : "abcd"]
["Mondays" : "1234"]
["Not Categorized" : "pqrs"]
["Tuesdays" : "5678"]
I want to sort the HashMap based on keys and additional to this I need "Not Categorized" to be the last one to retrieve.
So expected while iterating over keySet is
["Mondays", "Tuesdays", "Wednesdays", "Not Categorized"] i.e. sorted on keys and "Not Categorized" is the last one
Thought of going for HashMap while creating and at the end add ["Not Categorized" : "pqrs"] but HashMap does not guarantee the order :)
Any other pointers for the solution?
Are you specifically excluding TreeMap for some external reason? If not you could obviously use TreeMap with a specially made Comparator.
Have you considered any of the other SortedMaps?
If TreeMap is definitely out I would extend HashMap and make it look like there is always one more entry but that is certainly not a trivial piece of work. You should have a very good reason not to use a SortedMap before going down this road.
Added
Here is an example of how you can make a particular entry always sort to the end using a TreeMap:
// This key should always appear at the end of the list.
public static final String AtEnd = "Always at the end";
// A sample map.
SortedMap<String, String> myMap =
new TreeMap<>(
new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
return o1.equals(AtEnd) ? 1 : o2.equals(AtEnd) ? -1 : o1.compareTo(o2);
}
});
private void test() {
myMap.put("Monday", "abc");
myMap.put("Tuesday", "def");
myMap.put("Wednesday", "ghi");
myMap.put(AtEnd, "XYZ");
System.out.println("myMap: "+myMap);
// {Monday=abc, Tuesday=def, Wednesday=ghi, Always at the end=XYZ}
}
I wonder if you are looking for some variant of that?
You can achieve this by using LinkedHashMap as it guarantees to return results in the order of insertion.
Also check the following post to understand difference between map types.
Difference between HashMap, LinkedHashMap and TreeMap
Or just a create a custom class which holds a different key than the value. Sort according to the key of that class. For your case make the key same value as the day, and for "Not Categorized" case ensure that its key starts later than any of the other keys, for example make it "Z_Not Categorized".
public ComplexKey
{
String key;
String value;
}
ComplexKey monday = new ComplexKey("monday", "monday");
ComplexKey notCategorized = new ComplexKey("Z_Not Categorized", "Not Categorized");
Then you can write a custom comparator which sort the values according to the key of complexKey class.
In your case I would use a TreeMap:
Map<DayOfWeek, Object> favoritesMap = new TreeMap<>();
where DayOfWeek is a class you declare like:
class DayOfWeek implements Comparable<DayOfWeek> {
as it's not convenient to sort days of wooks as strings.
In fact, the keys are always sorted. If you output the map a couple of times, you will find that the result remains the same.
First I'll gossip again on hashing:
The reason is hashing. Each object has hashCode() method. The hash space is like a large array which contains all the possible hash values as indices. When a new element is inserted into a HashSet or a new pair is put into a HashMap, it is placed in the hash space according to its hash code. If two elements have the same hash code, they will be compared with equals() method, if unequal, then the new element will be placed next to it.
Then if you know what happens there, you can implement some code like below:
import java.util.*;
class MyString {
private String str;
public MyString (String str) {
this.str = str;
}
public String toString () {
return str;
}
public boolean equals (Object obj) {
if (obj.getClass().equals(MyString.class)) {
return obj.toString().equals(str);
}
return false;
}
public int hashCode () {
if (str.equalsIgnoreCase("Not Categorized")) {
return Integer.MAX_VALUE;
} else if (str.hashCode() == Integer.MAX_VALUE) {
return 0;
}
return str.hashCode();
}
}
public class Test {
public static void main (String args[]) {
Map<MyString, String> m = new HashMap<MyString, String>();
m.put(new MyString("a"), "a");
m.put(new MyString("c"), "c");
m.put(new MyString("Not Categorized"), "NC");
m.put(new MyString("b"), "b");
Set<MyString> keys = m.keySet();
for (MyString k : keys) {
System.out.println(m.get(k));
}
}
}
The result is "Not Categorized" always comes at last. The reason is simple: it's hash value is always the maximum of integer.
The reason I create a String wrapper class is String class is final, it can't be extended. So in this way, you would have your class structure a little change, but not much.
It is possible to use TreeMap, though it would be less efficient:
public static void main (String args[]) {
Map<String, String> m = new TreeMap<String, String>(new Comparator<String>() {
public int compare (String s1, String s2) {
if (s1.equals(s2)) {
return 0;
}
if (s1.equalsIgnoreCase("Not Categorized")) {
return 1;
}
if (s2.equalsIgnoreCase("Not Categorized")) {
return -1;
}
if (s1.hashCode() > s2.hashCode()) {
return 1;
} else if (s1.hashCode() < s2.hashCode()) {
return -1
} else {
return 0;
}
}
public boolean equals (Object obj) {
return false;
}
});
m.put("a", "a");
m.put("c", "c");
m.put("Not Categorized", "NC");
m.put("b", "b");
Set<String> keys = m.keySet();
for (String k : keys) {
System.out.println(m.get(k));
}
}
The result is the same. It will sort all the elements, but it won't change the hashing order of other strings, it only ensures "Not Categorized" always comes to be the largest one.
Is there any easy way to get the keys for which same value exist?
Or more importantly, how can i get the number of same-value-more-than-once occurrences?
Consider the hashmap:
1->A
2->A
3->A
4->B
5->C
6->D
7->D
here same-value-more-than-once occurred 3 times(A two times, D one time).That(3) is what i want in return.
I could iterate over the hashmap by the keyset/map.values() list, but it seems quite cumbersome to do that way. Any suggestions or solutions?
EDIT :
My context is, i'm working on a timetable generator. The data-structure for a time-slot is
{String day-hour, HashMap<String,Event> Rooms}
For a day-hour, some Event-s are assigned on Rooms map. While checking the fitness of the solution, i need to know if one staff is assigned multiple events on same hour. Hence i want to check how many violations are there in Rooms map by the values Event.getStaff() .
EDIT :
Values are objects here, I don't want to count the occurrences of the same objects, rather a field of the object. The EVENT object has a field staff and i need to count the multiple occurrences of staffs.
I could iterate over the hashmap by the keyset/map.values() list, but it seems quite cumbersome to do that way.
Well it's inefficient, but there's not a lot you can do about that, without having some sort of multi-map to store reverse mappings of values to keys.
It doesn't have to be cumbersome in terms of code though, if you use Guava:
Multiset<String> counts = HashMultiSet.create(map.values());
for (Multiset.Entry<String> entry : counts.entrySet) {
if (entry.getCount() > 1) {
System.out.println(entry.getElement() + ": " + entry.getCount());
}
}
This is nice way I think:
int freq = Collections.frequency(map.values(), "A");
which returns "3" for your example. Cheers!
EDIT: sorry I misunderstood the question in my first attempt, this should do the trick:
int k = 0;
Set<String> set = new HashSet<String>(map.values());
for (String s : set) {
int i = Collections.frequency(map.values(), s);
k += i > 1 ? i - 1 : 0;
}
You will still not be able to retreive the actual keys though. But that was not the most important thing, right?
How about (expanding on Jon's answer)
Multiset<V> counts = HashMultiSet.create(map.values());
Predicate<Map.Entry<K,V>> pred = new Predicate<Map.Entry<K,V>>(){
public boolean apply(Map.Entry<K,V> entry){
return counts.count(entry.getValue()) > 1;
}
}
Map<K,V> result = Maps.filterEntries(map, pred);
This will result in a map where each key is mapped to a value that is duplicated.
This answer is only needed to address the first part of the question (the "less important part"), to get the keys that have duplicate values.
I don't know the context but what if you use a multimap:
Map<String, List<Integer>>
so this way your map would look like this:
A->1, 2, 3
B->4
C->5
D->6, 7
You could create a wrapper class around (Hash)Map, with decorating the put()-remove() methods to maintain another map, of which the values of the original Map are the keys, and the values are the numbers of occurrences. Then you just have to implement the method to query that...
However, this is rather tricky! You have to be careful not to have links to objects that are not in the map anymore... This could lead to a memory leak!
Also, null value tolerance has to be taken into count...
public static class MyCountingMap<K,V> implements Map<K,V> {
private final Map<K,V> internalMap;
//hashmap tolerates null as a key!
private final Map<V,Long> counterMap = new HashMap<V, Long>();
public MyCountingMap(Map<K, V> internalMap) {
super();
this.internalMap = internalMap;
}
#Override
public V put(K key, V value) {
boolean containedOriginally = internalMap.containsKey(key);
V origValue = internalMap.put(key, value);
updateCounterPut(containedOriginally, origValue, value);
return origValue;
}
#Override
public void putAll(Map<? extends K, ? extends V> m) {
//now this is the awkward part...
//this whole thing could be done through a loop and the put() method,
//but I'd prefer to use the original implementation...
for(Map.Entry<? extends K, ? extends V> entry :m.entrySet()) {
boolean containedOriginally = internalMap.containsKey(entry.getKey());
V origValue = internalMap.get(entry.getKey());
updateCounterPut(containedOriginally, origValue, entry.getValue());
}
internalMap.putAll(m);
}
// this method updates the counter
private void updateCounterPut(boolean containedOriginally, V origValue, V newValue) {
//if it was in the map, and it is different than the original, decrement
if(containedOriginally && isDifferent(origValue, newValue))
{
decrement(origValue);
}
//if it was NOT in the map, or the value differs
if(!containedOriginally || isDifferent(origValue, newValue)) {
increment(newValue);
}
}
// nothing special, just nicer to extract this to a method. Checks if the two values are the same or not.
private static boolean isDifferent(Object origValue, Object newValue) {
return ((origValue==null && newValue!=null) || !(origValue!=null && origValue.equals(newValue)));
}
//this method returns the counter value for the map value
public Long getValueCount(V value) {
return counterMap.get(value);
}
#Override
public V remove(Object key) {
V toReturn = internalMap.remove(key);
if(toReturn!=null) {
decrement(toReturn);
}
return toReturn;
}
private void increment(V value) {
Long count = counterMap.get(value);
if(count == null) {
count = 0L;
}
counterMap.put(value, count+1);
}
private void decrement(V value) {
Long count = counterMap.get(value);
if(count == null) {
count = 0L;
}
//last! Have to remove reference to prevent memory leak!!
if(count == 1L) {
counterMap.remove(value);
} else {
counterMap.put(value, count-1);
}
}
//... boring wrapper methods ...
public void clear() { internalMap.clear(); }
public boolean containsKey(Object key) { return internalMap.containsKey(key); }
public boolean containsValue(Object value) { return internalMap.containsValue(value); }
public Set<Entry<K, V>> entrySet() { return internalMap.entrySet(); }
public V get(Object key) { return internalMap.get(key); }
public boolean isEmpty() { return internalMap.isEmpty(); }
public Set<K> keySet() { return internalMap.keySet(); }
public int size() { return internalMap.size(); }
public Collection<V> values() { return internalMap.values(); }
}