经常有一种需求,是需要存储键值对,放入一个对象对应的使用次数。
然后需要获取前10%、20%等数据。如果进行Map的全量排序输出会非常慢,因此需要用TreeMap。
使用
TreeMap<Integer,Set<T>>
记录这个调用次数下的对象集合,HashMap<T,Integer>
记录这个对象的调用次数。
在使用时,先查HashMap再在TreeMap中操作数据。
包装后如下:
@Test public void testHashMap() {
Map<String, Integer> topMap = new HashMap<>();
List<String> list = new ArrayList<String>(100000);
long st = System.currentTimeMillis();
int totalSize = 10000;
for (int i = 0; i < totalSize; i++) {
String str = null;
if (Math.random() > 0.5) {
if (list.size() == 0)
continue;
int choice = (int) (Math.random() * list.size());
str = list.get(choice == list.size() ? choice - 1 : choice);
} else {
str = UUID.randomUUID().toString();
list.add(str);
}
if (topMap.containsKey(str)) {
topMap.put(str, topMap.get(str) + 1);
} else
topMap.put(str, 1);
}
long ed = System.currentTimeMillis();
System.out.println("put data" + (ed - st));
st = System.currentTimeMillis();
for (int i = 0; i < totalSize; i++) {
String str = null;
if (Math.random() > 0.5) {
if (list.size() == 0)
continue;
int choice = (int) (Math.random() * list.size());
str = list.get(choice == list.size() ? choice - 1 : choice);
} else {
List<Map.Entry<String, Integer>> list1 =
new ArrayList<Map.Entry<String, Integer>>(topMap.entrySet());
Collections.sort(list1, new Comparator<Map.Entry<String, Integer>>() {
@Override public int compare(Map.Entry<String, Integer> o1,
Map.Entry<String, Integer> o2) {
return o2.getValue().compareTo(o1.getValue());
}
});
}
if (topMap.containsKey(str)) {
topMap.put(str, topMap.get(str) + 1);
} else
topMap.put(str, 1);
}
ed = System.currentTimeMillis();
System.out.println("get data" + (ed - st));
System.out.println(topMap.size() + " ");
}
@Test public void testSortTreeMap() {
//test million data
TopMap<String> topMap = new TopMap<String>();
Map<String, Integer> map = new HashMap<>();
List<String> list = new ArrayList<String>(100000);
long st = System.currentTimeMillis();
int totalSize = 1000000;
for (int i = 0; i < totalSize; i++) {
String str = null;
if (Math.random() > 0.5) {
if (list.size() == 0)
continue;
int choice = (int) (Math.random() * list.size());
str = list.get(choice == list.size() ? choice - 1 : choice);
} else {
str = UUID.randomUUID().toString();
list.add(str);
}
topMap.put(str);
}
long ed = System.currentTimeMillis();
System.out.println("put data" + (ed - st));
st = System.currentTimeMillis();
for (int i = 0; i < totalSize; i++) {
String str = null;
if (Math.random() > 0.5) {
if (list.size() == 0)
continue;
int choice = (int) (Math.random() * list.size());
str = list.get(choice == list.size() ? choice - 1 : choice);
} else {
List<String> list1 = topMap.get(true, 0.001);
}
if (str != null)
topMap.put(str);
}
ed = System.currentTimeMillis();
System.out.println("get data" + (ed - st));
System.out.println(topMap.size() + " " + topMap.treeSize());
// List<String> list1 = topMap.get();
// for (String s : list1) {
// System.out.println(s);
// }
for (Map.Entry entry : topMap.treeMap.entrySet()) {
System.out.println(entry.getKey() + "," + ((Set) (entry.getValue())).size());
}
}
//
public static class TopMap<T> {
TreeMap<Integer, Set<T>> treeMap;
Map<T, Integer> map;
public TopMap() {
treeMap = new TreeMap<Integer, Set<T>>();
map = new HashMap<T, Integer>();
}
public TopMap(boolean desc) {
treeMap = new TreeMap<Integer, Set<T>>(new Comparator<Integer>() {
@Override public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
map = new HashMap<T, Integer>();
}
public void put(T key) {
int tmp = 0;
Set<T> set = null;
if (map.containsKey(key)) {
tmp = map.get(key);
set = treeMap.get(tmp);
if (set != null) {
set.remove(key);
if (set.isEmpty())
treeMap.remove(tmp);
}
}
tmp += 1;
map.put(key, tmp);
set = treeMap.get(tmp);
if (set == null)
set = new HashSet<T>();
set.add(key);
treeMap.put(tmp, set);
}
public int treeSize() {
return treeMap.size();
}
public int size() {
return map.size();
}
public List<T> get() {
return get(treeMap.entrySet());
}
public List<T> get(Set<Map.Entry<Integer, Set<T>>> entrySet) {
List<T> ret = new LinkedList<T>();
for (Map.Entry<Integer, Set<T>> entry : entrySet) {
ret.addAll(entry.getValue());
}
return ret;
}
public List<T> get(double percent) {
return get(treeMap.entrySet(), percent);
}
public List<T> get(boolean desc, double parcent) {
if (desc)
return get(treeMap.descendingMap().entrySet(), parcent);
return get(treeMap.entrySet(), parcent);
}
public List<T> get(Set<Map.Entry<Integer, Set<T>>> entrySet, double percent) {
int capacity = (int) (map.size() * percent);
List<T> ret = new LinkedList<T>();
for (Map.Entry<Integer, Set<T>> entry : entrySet) {
Set<T> set = entry.getValue();
if (capacity > set.size()) {
ret.addAll(set);
capacity -= set.size();
} else {
for (T t : set) {
ret.add(t);
if (--capacity <= 0)
break;
}
}
if (capacity <= 0)
break;
}
return ret;
}
}