package com.musicg.math.rank; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; public class MapRankInteger implements MapRank{ private Map map; private boolean acsending=true; public MapRankInteger(Map<?,Integer> map, boolean acsending){ this.map=map; this.acsending=acsending; } public List getOrderedKeyList(int numKeys, boolean sharpLimit){ // if sharp limited, will return sharp numKeys, otherwise will return until the values not equals the exact key's value Set mapEntrySet=map.entrySet(); List keyList=new LinkedList(); // if the numKeys is larger than map size, limit it if (numKeys>map.size()){ numKeys=map.size(); } // end if the numKeys is larger than map size, limit it if (map.size()>0){ int[] array=new int[map.size()]; int count=0; // get the pass values Iterator<Entry> mapIterator=mapEntrySet.iterator(); while (mapIterator.hasNext()){ Entry entry=mapIterator.next(); array[count++]=(Integer)entry.getValue(); } // end get the pass values int targetindex; if (acsending){ targetindex=numKeys; } else{ targetindex=array.length-numKeys; } int passValue=getOrderedValue(array,targetindex); // this value is the value of the numKey-th element // get the passed keys and values Map passedMap=new HashMap(); List<Integer> valueList=new LinkedList<Integer>(); mapIterator=mapEntrySet.iterator(); while (mapIterator.hasNext()){ Entry entry=mapIterator.next(); int value=(Integer)entry.getValue(); if ((acsending && value<=passValue) || (!acsending && value>=passValue)){ passedMap.put(entry.getKey(), value); valueList.add(value); } } // end get the passed keys and values // sort the value list Integer[] listArr=new Integer[valueList.size()]; valueList.toArray(listArr); Arrays.sort(listArr); // end sort the value list // get the list of keys int resultCount=0; int index; if (acsending){ index=0; } else{ index=listArr.length-1; } if (!sharpLimit){ numKeys=listArr.length; } while (true){ int targetValue=(Integer)listArr[index]; Iterator<Entry> passedMapIterator=passedMap.entrySet().iterator(); while(passedMapIterator.hasNext()){ Entry entry=passedMapIterator.next(); if ((Integer)entry.getValue()==targetValue){ keyList.add(entry.getKey()); passedMapIterator.remove(); resultCount++; break; } } if (acsending){ index++; } else{ index--; } if (resultCount>=numKeys){ break; } } // end get the list of keys } return keyList; } private int getOrderedValue(int[] array, int index){ locate(array,0,array.length-1,index); return array[index]; } // sort the partitions by quick sort, and locate the target index private void locate(int[] array, int left, int right, int index) { int mid=(left+right)/2; //System.out.println(left+" to "+right+" ("+mid+")"); if (right==left){ //System.out.println("* "+array[targetIndex]); //result=array[targetIndex]; return; } if(left < right) { int s = array[mid]; int i = left - 1; int j = right + 1; while(true) { while(array[++i] < s) ; while(array[--j] > s) ; if(i >= j) break; swap(array, i, j); } //System.out.println("2 parts: "+left+"-"+(i-1)+" and "+(j+1)+"-"+right); if (i>index){ // the target index in the left partition //System.out.println("left partition"); locate(array, left, i-1,index); } else{ // the target index in the right partition //System.out.println("right partition"); locate(array, j+1, right,index); } } } private void swap(int[] array, int i, int j) { int t = array[i]; array[i] = array[j]; array[j] = t; } }