当前位置:   article > 正文

经典排序之topK问题_topk查询不起作用

topk查询不起作用

经典排序之topK问题

现代大数据环境下。对于大数据的处理很平常。

场景还原

对于给定的1亿或者无上限的数据。排序出top 50的数据。

问题分析

  • 如此大的数据让其全部加载到内存中再次排序肯定是不行的。内存不够啊
  • 再资源有限的情况下,使用分布式计算也是很有限的,因为小公司基本没可能

方案分析

对此有人给出了一个解决方案:堆排序。

  • 堆树有一个很大的特点,堆顶要么最大,要么最小。
  • 新增一个堆顶元素可以快速的重新堆化
  • 对于大数据量我们可以每次加载一定的数据而不用全部加载

代码再现

public class ObjectTopK<E> {

	//要排序的数量
    private int k;
    //数据存储
    private List<E> list;
    //比较器
    private Comparator comparator;
    //是否初始化堆
    private boolean init=false;
    
    public ObjectTopK(int k){
		this.k = k;
		//初始化大小
		list = new ArrayList<E>(k);
	}
	
	public ObjectTopK(int k,Comparator<? super E> comparator){
		this.k = k;
		//初始化大小
		list = new ArrayList<E>(k);
		this.comparator = comparator;
	}
	
	/**
	 * 添加元素
	 * @param e
	 */
	public void add(E e) {
		if( list.size() < k ) {
			list.add(e);
		}else if( !init ){
			buildMinHeap();
			init=true;
		}else {
			if( comparator != null && comparator.compare(e, list.get(0)) > 0) {
				list.set(0, e);
				buildMinHeap(0, list.size());
			}else if(((Comparable)e).compareTo((Comparable)list.get(0)) > 0) {
				list.set(0, e);
				buildMinHeap(0, list.size());
			}
			
		}
	}
	/**
	 * 构造最小堆
	 */
	private void buildMinHeap(){
		for(int i=list.size()/2 -1 ; i>=0 ; i--) {
			buildMinHeap(i, list.size());
//			print();
//			System.out.println();
		}
	}
	
	/**
	 * 堆化
	 */
	private void buildMinHeap(int start, int end) {
		if( comparator != null ) {
			int left = 2*start+1;
			while(left < end) {
				int min = left;
				if( left+1 < end && comparator.compare(list.get(left+1), list.get(left))<0){
					min = left+1;
				}
				if(comparator.compare(list.get(start), list.get(min))<0) {
					break;
				} else {
					E temp = list.get(min);
					list.set(min, list.get(start));
					list.set(start, temp);
					start = min;
					left = 2*start + 1;
				}
			}
		}else if( list.get(0) instanceof Comparable){
			int left = 2*start+1;
			while(left < end) {
				int min = left;
				if( left+1 < end && ((Comparable)list.get(left+1)).compareTo((Comparable)list.get(left)) < 0){
					min = left+1;
				}
				if( ((Comparable)list.get(start)).compareTo((Comparable)list.get(min)) < 0 ) {
					break;
				} else {
					E temp = list.get(min);
					list.set(min, list.get(start));
					list.set(start, temp);
					start = min;
					left = 2*start + 1;
				}
			}
		} else {
			throw new RuntimeException("数据不能比较");
		}
	}
	
	/**
	 * 堆排序
	 */
	public void sort() {
		for(int i=list.size()-1; i>=0; i--) {
			E temp = list.get(0);
			list.set(0, list.get(i));
			list.set(i, temp);
			buildMinHeap(0, i);
		}
	}
	
	/**
	 * 输出结果
	 */
	public void print() {
		for(E e: list) {
			System.out.print(e+" ");
		}
	}
	public static void main(String[] args) throws IOException {
		ObjectTopK<Integer> obj = new ObjectTopK<Integer>(50);
		Random random = new Random();
		long start = System.currentTimeMillis();
		for(int i=0;i<Integer.MAX_VALUE;i++) {
			obj.add(random.nextInt(Integer.MAX_VALUE));
		}
		obj.sort();
		obj.print();
		System.out.println("=============================");
		System.out.println("21亿数据耗时:"+(System.currentTimeMillis()-start)/1000);
	}
	
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133

执行结果

2147483644 2147483643 2147483641 2147483639 2147483637 2147483637 2147483636 2147483633 2147483633 2147483632 2147483630 2147483629 2147483627 2147483627 2147483627 2147483626 2147483625 2147483625 2147483625 2147483619 2147483618 2147483618 2147483617 2147483612 2147483611 2147483611 2147483611 2147483609 2147483608 2147483607 2147483606 2147483606 2147483606 2147483605 2147483603 2147483602 2147483602 2147483599 2147483598 2147483597 2147483597 2147483597 2147483597 2147483592 2147483592 2147483590 2147483589 2147483589 2147483588 2147483588 =============================
21亿数据耗时:37

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/716847
推荐阅读
相关标签
  

闽ICP备14008679号