skiwi
skiwi

Reputation: 69269

Java creating a custom Map

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

Answers (1)

LaurentG
LaurentG

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

Related Questions