Reputation: 69269
I have two questions regarding my following code:
1) Is there any way I can implement Map
in this case, rather than extend just one direct implementation of the interface? I do not wish to write a whole Map implementation though. But it could be nice seeing that my implementation does not care what underlying Map implementation is being used.
2) Are there any bad practices?
ExtremesMap.java
package ocr.util;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
*
* @author student
*/
public class ExtremesMap extends HashMap<String, Integer> {
private Set<String> smallest;
private int smallestValue;
private Set<String> biggest;
private int biggestValue;
public ExtremesMap() {
super();
smallest = new HashSet<>();
smallestValue = Integer.MAX_VALUE;
biggest = new HashSet<>();
biggestValue = Integer.MIN_VALUE;
}
@Override
public void put(String key, Integer value) {
if (value == null) {
throw new IllegalArgumentException("ocr.util.ExtremesMap.put: value == null");
}
//TODO for real performance application implement own type of Map directly
Integer retrieveValue = super.get(key);
if (retrieveValue != null) {
throw new IllegalStateException("ocr.util.ExtremesMap.put: Not allowed to modify existing value: key = " + key);
}
else if (retrieveValue == value) {
return;
}
super.put(key, value);
if (value < smallestValue) {
smallest = new HashSet<>();
smallestValue = value;
}
else if (value == smallestValue) {
smallest.add(key);
}
if (value > biggestValue) {
biggest = new HashSet<>();
biggestValue = value;
}
else if (value == biggestValue) {
biggest.add(key);
}
}
public String getSmallestString() {
if (smallest.size() != 1) {
throw new IllegalStateException("ocr.util.ExtremesMap.getSmallest: smallest.size() != 1: smallest.size() = " + smallest.size());
}
return smallest.iterator().next();
}
public Set<String> getSmallestSet() {
return smallest;
}
public List<String> getSmallestList() {
return Arrays.asList(getSmallestArray());
}
public String[] getSmallestArray() {
return smallest.toArray(new String[smallest.size()]);
}
public String getBiggestString() {
if (biggest.size() != 1) {
throw new IllegalStateException("ocr.util.ExtremesMap.getBiggest: biggest.size() != 1: biggest.size() = " + biggest.size());
}
return biggest.iterator().next();
}
public Set<String> getBiggestSet() {
return biggest;
}
public List<String> getBiggestList() {
return Arrays.asList(getBiggestArray());
}
public String[] getBiggestArray() {
return biggest.toArray(new String[biggest.size()]);
}
}
Also there is one bug which I am unable to resolve in put()
:
method does not override or implement a method from a supertype
put(String,Integer) in ExtremesMap cannot implement put(K,V) in Map
return type void is not compatible with Integer
where K,V are type-variables:
K extends Object declared in interface Map
V extends Object declared in interface Map
What exactly goes wrong here?
Regards.
Upvotes: 3
Views: 10041
Reputation: 11757
As the error says, the put
signature is:
V put(K key, V value)
That means that your method put
should return Integer
and not void
:
public Integer put(String key, Integer value) { ... }
Concerning your first two questions, I would say that it is not a recommended practice to extend HashMap
, because you are changing the way a Map is working when you override put
. You should better use composition instead (a normal class which contains a private field Map
for internal use).
For a whole code review of your code, you could ask at Code Review StackExchange.
Upvotes: 4