1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時間:8:30-17:00
      你可能遇到了下面的問題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
      利用Java怎么對超大的文件進(jìn)行排序

      這篇文章將為大家詳細(xì)講解有關(guān)利用Java 怎么對超大的文件進(jìn)行排序,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。

      成都創(chuàng)新互聯(lián)公司網(wǎng)站建設(shè)由有經(jīng)驗的網(wǎng)站設(shè)計師、開發(fā)人員和項目經(jīng)理組成的專業(yè)建站團(tuán)隊,負(fù)責(zé)網(wǎng)站視覺設(shè)計、用戶體驗優(yōu)化、交互設(shè)計和前端開發(fā)等方面的工作,以確保網(wǎng)站外觀精美、成都網(wǎng)站建設(shè)、網(wǎng)站制作易于使用并且具有良好的響應(yīng)性。

      內(nèi)部排序

      先嘗試內(nèi)排,選2種排序方式:

      3路快排:

      private final int cutoff = 8;
      
      public  void perform(Comparable[] a) {
          perform(a,0,a.length - 1);
        }
      
        private  int median3(Comparable[] a,int x,int y,int z) {
          if(lessThan(a[x],a[y])) {
            if(lessThan(a[y],a[z])) {
              return y;
            }
            else if(lessThan(a[x],a[z])) {
              return z;
            }else {
              return x;
            }
          }else {
            if(lessThan(a[z],a[y])){
              return y;
            }else if(lessThan(a[z],a[x])) {
              return z;
            }else {
              return x;
            }
          }
        }
      
        private  void perform(Comparable[] a,int low,int high) {
          int n = high - low + 1;
          //當(dāng)序列非常小,用插入排序
          if(n <= cutoff) {
            InsertionSort insertionSort = SortFactory.createInsertionSort();
            insertionSort.perform(a,low,high);
            //當(dāng)序列中小時,使用median3
          }else if(n <= 100) {
            int m = median3(a,low,low + (n >>> 1),high);
            exchange(a,m,low);
            //當(dāng)序列比較大時,使用ninther
          }else {
            int gap = n >>> 3;
            int m = low + (n >>> 1);
            int m1 = median3(a,low,low + gap,low + (gap << 1));
            int m2 = median3(a,m - gap,m,m + gap);
            int m3 = median3(a,high - (gap << 1),high - gap,high);
            int ninther = median3(a,m1,m2,m3);
            exchange(a,ninther,low);
          }
      
          if(high <= low)
            return;
          //lessThan
          int lt = low;
          //greaterThan
          int gt = high;
          //中心點(diǎn)
          Comparable pivot = a[low];
          int i = low + 1;
      
          /*
          * 不變式:
          *  a[low..lt-1] 小于pivot -> 前部(first)
          *  a[lt..i-1] 等于 pivot -> 中部(middle)
          *  a[gt+1..n-1] 大于 pivot -> 后部(final)
          *
          *  a[i..gt] 待考察區(qū)域
          */
      
          while (i <= gt) {
            if(lessThan(a[i],pivot)) {
              //i-> ,lt ->
              exchange(a,lt++,i++);
            }else if(lessThan(pivot,a[i])) {
              exchange(a,i,gt--);
            }else{
              i++;
            }
          }
      
          // a[low..lt-1] < v = a[lt..gt] < a[gt+1..high].
          perform(a,low,lt - 1);
          perform(a,gt + 1,high);
        }

      歸并排序:

       /**
         * 小于等于這個值的時候,交給插入排序
         */
        private final int cutoff = 8;
      
        /**
         * 對給定的元素序列進(jìn)行排序
         *
         * @param a 給定元素序列
         */
        @Override
        public  void perform(Comparable[] a) {
          Comparable[] b = a.clone();
          perform(b, a, 0, a.length - 1);
        }
      
        private  void perform(Comparable[] src,Comparable[] dest,int low,int high) {
          if(low >= high)
            return;
      
          //小于等于cutoff的時候,交給插入排序
          if(high - low <= cutoff) {
            SortFactory.createInsertionSort().perform(dest,low,high);
            return;
          }
      
          int mid = low + ((high - low) >>> 1);
          perform(dest,src,low,mid);
          perform(dest,src,mid + 1,high);
      
          //考慮局部有序 src[mid] <= src[mid+1]
          if(lessThanOrEqual(src[mid],src[mid+1])) {
            System.arraycopy(src,low,dest,low,high - low + 1);
          }
      
          //src[low .. mid] + src[mid+1 .. high] -> dest[low .. high]
          merge(src,dest,low,mid,high);
        }
      
        private  void merge(Comparable[] src,Comparable[] dest,int low,int mid,int high) {
      
          for(int i = low,v = low,w = mid + 1; i <= high; i++) {
            if(w > high || v <= mid && lessThanOrEqual(src[v],src[w])) {
              dest[i] = src[v++];
            }else {
              dest[i] = src[w++];
            }
          }
        }

      數(shù)據(jù)太多,遞歸太深 ->棧溢出?加大Xss?
      數(shù)據(jù)太多,數(shù)組太長 -> OOM?加大Xmx?

      耐心不足,沒跑出來.而且要將這么大的文件讀入內(nèi)存,在堆中維護(hù)這么大個數(shù)據(jù)量,還有內(nèi)排中不斷的拷貝,對棧和堆都是很大的壓力,不具備通用性。

      sort命令來跑

      sort -n bigdata -o bigdata.sorted

      跑了多久呢?24分鐘.

      為什么這么慢?

      粗略的看下我們的資源:
      1. 內(nèi)存
      jvm-heap/stack,native-heap/stack,page-cache,block-buffer
      2. 外存
      swap + 磁盤

      數(shù)據(jù)量很大,函數(shù)調(diào)用很多,系統(tǒng)調(diào)用很多,內(nèi)核/用戶緩沖區(qū)拷貝很多,臟頁回寫很多,io-wait很高,io很繁忙,堆棧數(shù)據(jù)不斷交換至swap,線程切換很多,每個環(huán)節(jié)的鎖也很多.

      總之,內(nèi)存吃緊,問磁盤要空間,臟數(shù)據(jù)持久化過多導(dǎo)致cache頻繁失效,引發(fā)大量回寫,回寫線程高,導(dǎo)致cpu大量時間用于上下文切換,一切,都很糟糕,所以24分鐘不細(xì)看了,無法忍受.

      位圖法

       private BitSet bits;
      
        public void perform(
            String largeFileName,
            int total,
            String destLargeFileName,
            Castor castor,
            int readerBufferSize,
            int writerBufferSize,
            boolean asc) throws IOException {
      
          System.out.println("BitmapSort Started.");
          long start = System.currentTimeMillis();
          bits = new BitSet(total);
          InputPart largeIn = PartFactory.createCharBufferedInputPart(largeFileName, readerBufferSize);
          OutputPart largeOut = PartFactory.createCharBufferedOutputPart(destLargeFileName, writerBufferSize);
          largeOut.delete();
      
          Integer data;
          int off = 0;
          try {
            while (true) {
              data = largeIn.read();
              if (data == null)
                break;
              int v = data;
              set(v);
              off++;
            }
            largeIn.close();
            int size = bits.size();
            System.out.println(String.format("lines : %d ,bits : %d", off, size));
      
            if(asc) {
              for (int i = 0; i < size; i++) {
                if (get(i)) {
                  largeOut.write(i);
                }
              }
            }else {
              for (int i = size - 1; i >= 0; i--) {
                if (get(i)) {
                  largeOut.write(i);
                }
              }
            }
      
            largeOut.close();
            long stop = System.currentTimeMillis();
            long elapsed = stop - start;
            System.out.println(String.format("BitmapSort Completed.elapsed : %dms",elapsed));
          }finally {
            largeIn.close();
            largeOut.close();
          }
        }
      
        private void set(int i) {
          bits.set(i);
        }
      
        private boolean get(int v) {
          return bits.get(v);
        }

      nice!跑了190秒,3分來鐘.
      以核心內(nèi)存4663M/32大小的空間跑出這么個結(jié)果,而且大量時間在用于I/O,不錯.

      問題是,如果這個時候突然內(nèi)存條壞了1、2根,或者只有極少的內(nèi)存空間怎么搞?

      外部排序

      該外部排序上場了.
      外部排序干嘛的?

      內(nèi)存極少的情況下,利用分治策略,利用外存保存中間結(jié)果,再用多路歸并來排序; map-reduce的嫡系.

      利用Java 怎么對超大的文件進(jìn)行排序 

      利用Java 怎么對超大的文件進(jìn)行排序

      1.分

      內(nèi)存中維護(hù)一個極小的核心緩沖區(qū)memBuffer,將大文件bigdata按行讀入,搜集到memBuffer滿或者大文件讀完時,對memBuffer中的數(shù)據(jù)調(diào)用內(nèi)排進(jìn)行排序,排序后將有序結(jié)果寫入磁盤文件bigdata.xxx.part.sorted.
      循環(huán)利用memBuffer直到大文件處理完畢,得到n個有序的磁盤文件:

      利用Java 怎么對超大的文件進(jìn)行排序

      2.合

      現(xiàn)在有了n個有序的小文件,怎么合并成1個有序的大文件?
      把所有小文件讀入內(nèi)存,然后內(nèi)排?
      (⊙o⊙)…
      no!

      利用如下原理進(jìn)行歸并排序:

      利用Java 怎么對超大的文件進(jìn)行排序 

      我們舉個簡單的例子:

      文件1:3,6,9
      文件2:2,4,8
      文件3:1,5,7

      第一回合:
      文件1的最小值:3 , 排在文件1的第1行
      文件2的最小值:2,排在文件2的第1行
      文件3的最小值:1,排在文件3的第1行
      那么,這3個文件中的最小值是:min(1,2,3) = 1
      也就是說,最終大文件的當(dāng)前最小值,是文件1、2、3的當(dāng)前最小值的最小值,繞么?
      上面拿出了最小值1,寫入大文件.

      第二回合:
      文件1的最小值:3 , 排在文件1的第1行
      文件2的最小值:2,排在文件2的第1行
      文件3的最小值:5,排在文件3的第2行
      那么,這3個文件中的最小值是:min(5,2,3) = 2
      將2寫入大文件.

      也就是說,最小值屬于哪個文件,那么就從哪個文件當(dāng)中取下一行數(shù)據(jù).(因為小文件內(nèi)部有序,下一行數(shù)據(jù)代表了它當(dāng)前的最小值)

      最終的時間,跑了771秒,13分鐘左右.

      less bigdata.sorted.text
      ...
      9999966
      9999967
      9999968
      9999969
      9999970
      9999971
      9999972
      9999973
      9999974
      9999975
      9999976
      9999977
      9999978
      ...

      關(guān)于利用Java 怎么對超大的文件進(jìn)行排序就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。


      標(biāo)題名稱:利用Java怎么對超大的文件進(jìn)行排序
      本文鏈接:http://www.ef60e0e.cn/article/jjiioi.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        东乡族自治县| 麻栗坡县| 万年县| 隆尧县| 神农架林区| 郎溪县| 洛扎县| 台南市| 霍邱县| 三门峡市| 卓资县| 三原县| 拉萨市| 宣恩县| 行唐县| 茂名市| 中西区| 句容市| 北海市| 新密市| 博客| 航空| 老河口市| 安宁市| 江西省| 友谊县| 张家口市| 田林县| 道真| 民和| 常宁市| 周口市| 江永县| 大宁县| 衡阳县| 邵阳市| 涿州市| 勃利县| 石首市| 简阳市| 徐水县|