class Histotable<K> extends TreeMap<K,Long> {    
    private static final long serialVersionUID = 310306238032568623L;
    
    /**
     * Record one more occurrence of the given object key.
     * 
     * @param key Object key.
     */
    public void tally(K key) {
        tally(key,1L);
    }
    
    /**
     * Record <i>count</i> more occurrence(s) of the given object key.
     * 
     * @param key Object key.
     */
    public synchronized void tally(K key,long count) {
        long tally = containsKey(key) ? get(key) : 0; 
        tally += count; 
        if(tally!=0) {
            put(key,tally);
        } else {
            remove(key);
        }
    }
    
    /**
     * Get a SortedSet that, when filled with (String key)-&gt;(long count) 
     * Entry instances, sorts them by (count, key) descending, as is useful 
     * for most-frequent displays. 
     * 
     * Static to allow reuse elsewhere (TopNSet) until a better home for
     * this utility method is found. 
     * 
     * @return TreeSet with suitable Comparator
     */
    public static TreeSet<Map.Entry<?, Long>> getEntryByFrequencySortedSet() {
        // sorted by count
        TreeSet<Map.Entry<?,Long>> sorted = 
          new TreeSet<Map.Entry<?,Long>>(
           new Comparator<Map.Entry<?,Long>>() {
            public int compare(Map.Entry<?,Long> e1, 
                    Map.Entry<?,Long> e2) {
                long firstVal = e1.getValue();
                long secondVal = e2.getValue();
                if (firstVal < secondVal) { return 1; }
                if (secondVal < firstVal) { return -1; }
                // If the values are the same, sort by keys.
                String firstKey = ((Map.Entry<?,Long>) e1).getKey().toString();
                String secondKey = ((Map.Entry<?,Long>) e2).getKey().toString();
                return firstKey.compareTo(secondKey);
            }
        });
        return sorted;
    }
    
    /**
     * @return Return an up-to-date count-descending sorted version of the totaled info.
     */
    public TreeSet<Map.Entry<?,Long>> getSortedByCounts() {
        TreeSet<java.util.Map.Entry<?, Long>> sorted = getEntryByFrequencySortedSet();
        sorted.addAll(entrySet());
        return sorted; 
    }
    
    /**
     * @return Return an up-to-date sorted version of the totaled info.
     */
    public Set<Map.Entry<K,Long>> getSortedByKeys() {
        return entrySet();
    }
    
    /**
     * Return the largest value of any key that is larger than 0. If no 
     * values or no value larger than zero, return zero. 
     * 
     * @return long largest value or zero if none larger than zero
     */
    public long getLargestValue() {
        long largest = 0; 
        for (Long el : values()) {
            if (el > largest) {
                largest = el;
            }
        }
        return largest;
    }
    
    /**
     * Return the total of all tallies. 
     * 
     * @return long total of all tallies
     */
    public long getTotal() {<FILL_FUNCTION_BODY>}
    
    /**
     * Utility method to convert a key-&gt;Long into
     * the string "count key".
     * 
     * @param e Map key.
     * @return String 'count key'.
     */
    @SuppressWarnings("unchecked")
    public static String entryString(Object e) {
        Map.Entry<?,Long> entry = (Map.Entry<?,Long>) e;
        return entry.getValue() + " " + entry.getKey();
    }
    
    public long add(Histotable<K> ht) {
        long net = 0;
        for (K key : ht.keySet()) {
            long change = ht.get(key);
            net += change;
            tally(key,change);
        }
        return net;
    }
    public long subtract(Histotable<K> ht) {
        long net = 0; 
        for (K key : ht.keySet()) {
            long change = ht.get(key);
            net -= change;
            tally(key,-change);
        }
        return net;
    }

    /** Return 0 instead of null for absent keys. 
     * 
     * @see java.util.TreeMap#get(java.lang.Object)
     */
    @Override
    public Long get(Object key) {
        Long val = super.get(key);
        return val == null ? 0 : val;
    }
    
    
}

        long total = 0; 
        for (Long el : values()) {
            total += el; 
        }
        return total;
    
<methods>public void <init>() ,public void <init>(Comparator<? super K>) ,public void <init>(Map<? extends K,? extends java.lang.Long>) ,public void <init>(SortedMap<K,? extends java.lang.Long>) ,public Entry<K,java.lang.Long> ceilingEntry(K) ,public K ceilingKey(K) ,public void clear() ,public java.lang.Object clone() ,public Comparator<? super K> comparator() ,public java.lang.Long compute(K, BiFunction<? super K,? super java.lang.Long,? extends java.lang.Long>) ,public java.lang.Long computeIfAbsent(K, Function<? super K,? extends java.lang.Long>) ,public java.lang.Long computeIfPresent(K, BiFunction<? super K,? super java.lang.Long,? extends java.lang.Long>) ,public boolean containsKey(java.lang.Object) ,public boolean containsValue(java.lang.Object) ,public NavigableSet<K> descendingKeySet() ,public NavigableMap<K,java.lang.Long> descendingMap() ,public Set<Entry<K,java.lang.Long>> entrySet() ,public Entry<K,java.lang.Long> firstEntry() ,public K firstKey() ,public Entry<K,java.lang.Long> floorEntry(K) ,public K floorKey(K) ,public void forEach(BiConsumer<? super K,? super java.lang.Long>) ,public java.lang.Long get(java.lang.Object) ,public SortedMap<K,java.lang.Long> headMap(K) ,public NavigableMap<K,java.lang.Long> headMap(K, boolean) ,public Entry<K,java.lang.Long> higherEntry(K) ,public K higherKey(K) ,public Set<K> keySet() ,public Entry<K,java.lang.Long> lastEntry() ,public K lastKey() ,public Entry<K,java.lang.Long> lowerEntry(K) ,public K lowerKey(K) ,public java.lang.Long merge(K, java.lang.Long, BiFunction<? super java.lang.Long,? super java.lang.Long,? extends java.lang.Long>) ,public NavigableSet<K> navigableKeySet() ,public Entry<K,java.lang.Long> pollFirstEntry() ,public Entry<K,java.lang.Long> pollLastEntry() ,public java.lang.Long put(K, java.lang.Long) ,public void putAll(Map<? extends K,? extends java.lang.Long>) ,public java.lang.Long putIfAbsent(K, java.lang.Long) ,public java.lang.Long remove(java.lang.Object) ,public java.lang.Long replace(K, java.lang.Long) ,public boolean replace(K, java.lang.Long, java.lang.Long) ,public void replaceAll(BiFunction<? super K,? super java.lang.Long,? extends java.lang.Long>) ,public int size() ,public SortedMap<K,java.lang.Long> subMap(K, K) ,public NavigableMap<K,java.lang.Long> subMap(K, boolean, K, boolean) ,public SortedMap<K,java.lang.Long> tailMap(K) ,public NavigableMap<K,java.lang.Long> tailMap(K, boolean) ,public Collection<java.lang.Long> values() <variables>private static final boolean BLACK,private static final boolean RED,private static final java.lang.Object UNBOUNDED,private final Comparator<? super K> comparator,private transient NavigableMap<K,java.lang.Long> descendingMap,private transient EntrySet entrySet,private transient int modCount,private transient KeySet<K> navigableKeySet,private transient Entry<K,java.lang.Long> root,private static final long serialVersionUID,private transient int size