001: /*
002: * Histotable.java
003: *
004: * Created on Aug 5, 2004
005: *
006: * $Id: Histotable.java 5047 2007-04-10 01:47:42Z gojomo $
007: *
008: * Copyright (C) 2007 Internet Archive.
009: *
010: * This file is part of the Heritrix web crawler (crawler.archive.org).
011: *
012: * Heritrix is free software; you can redistribute it and/or modify
013: * it under the terms of the GNU Lesser Public License as published by
014: * the Free Software Foundation; either version 2.1 of the License, or
015: * any later version.
016: *
017: * Heritrix is distributed in the hope that it will be useful,
018: * but WITHOUT ANY WARRANTY; without even the implied warranty of
019: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
020: * GNU Lesser Public License for more details.
021: *
022: * You should have received a copy of the GNU Lesser Public License
023: * along with Heritrix; if not, write to the Free Software
024: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
025: */
026:
027: package org.archive.util;
028:
029: import java.util.Comparator;
030: import java.util.HashMap;
031: import java.util.Map;
032: import java.util.TreeSet;
033:
034: /**
035: * Collect and report frequency information.
036: *
037: * Assumes external synchornization.
038: *
039: * @author gojomo
040: */
041: public class Histotable<K> extends HashMap<K, Long> {
042: private static final long serialVersionUID = 310306238032568623L;
043:
044: /**
045: * Record one more occurence of the given object key.
046: *
047: * @param key Object key.
048: */
049: public void tally(K key) {
050: tally(key, 1L);
051: }
052:
053: /**
054: * Record <i>count</i> more occurence(s) of the given object key.
055: *
056: * @param key Object key.
057: */
058: public void tally(K key, long count) {
059: if (containsKey(key)) {
060: put(key, get(key) + count);
061: } else {
062: // if we didn't find this key add it
063: put(key, count);
064: }
065: }
066:
067: /**
068: * @return Return an up-to-date sorted version of the totalled info.
069: */
070: public TreeSet getSortedByCounts() {
071: // sorted by count
072: TreeSet<Map.Entry<K, Long>> sorted = new TreeSet<Map.Entry<K, Long>>(
073: new Comparator<Map.Entry<K, Long>>() {
074: public int compare(Map.Entry<K, Long> e1,
075: Map.Entry<K, Long> e2) {
076: long firstVal = e1.getValue();
077: long secondVal = e2.getValue();
078: if (firstVal < secondVal) {
079: return 1;
080: }
081: if (secondVal < firstVal) {
082: return -1;
083: }
084: // If the values are the same, sort by keys.
085: String firstKey = (String) ((Map.Entry) e1)
086: .getKey();
087: String secondKey = (String) ((Map.Entry) e2)
088: .getKey();
089: return firstKey.compareTo(secondKey);
090: }
091: });
092:
093: sorted.addAll(entrySet());
094: return sorted;
095: }
096:
097: /**
098: * @return Return an up-to-date sorted version of the totalled info.
099: */
100: public TreeSet getSortedByKeys() {
101: TreeSet<Map.Entry<K, Long>> sorted = new TreeSet<Map.Entry<K, Long>>(
102: new Comparator<Map.Entry<K, Long>>() {
103: @SuppressWarnings("unchecked")
104: public int compare(Map.Entry<K, Long> e1,
105: Map.Entry<K, Long> e2) {
106: K firstKey = e1.getKey();
107: K secondKey = e2.getKey();
108: // If the values are the same, sort by keys.
109: return ((Comparable<K>) firstKey)
110: .compareTo(secondKey);
111: }
112: });
113: sorted.addAll(entrySet());
114: return sorted;
115: }
116:
117: /**
118: * Return the largest value of any key that is larger than 0. If no
119: * values or no value larger than zero, return zero.
120: *
121: * @return long largest value or zero if none larger than zero
122: */
123: public long getLargestValue() {
124: long largest = 0;
125: for (Long el : values()) {
126: if (el > largest) {
127: largest = el;
128: }
129: }
130: return largest;
131: }
132:
133: /**
134: * Return the total of all tallies.
135: *
136: * @return long total of all tallies
137: */
138: public long getTotal() {
139: long total = 0;
140: for (Long el : values()) {
141: total += el;
142: }
143: return total;
144: }
145:
146: /**
147: * Utility method to convert a key->Long into
148: * the string "count key".
149: *
150: * @param e Map key.
151: * @return String 'count key'.
152: */
153: public static String entryString(Object e) {
154: Map.Entry entry = (Map.Entry) e;
155: return entry.getValue() + " " + entry.getKey();
156: }
157:
158: public long add(Histotable<K> ht) {
159: long net = 0;
160: for (K key : ht.keySet()) {
161: long change = ht.get(key);
162: net += change;
163: tally(key, change);
164: }
165: return net;
166: }
167:
168: public long subtract(Histotable<K> ht) {
169: long net = 0;
170: for (K key : ht.keySet()) {
171: long change = ht.get(key);
172: net -= change;
173: tally(key, -change);
174: }
175: return net;
176: }
177: }
|