<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    xylz,imxylz

    關注后端架構、中間件、分布式和并發編程

       :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      111 隨筆 :: 10 文章 :: 2680 評論 :: 0 Trackbacks
    我需要一個從集合N中隨機選擇M個子元素的算法。 當然最好的辦法是將集合打亂順序,然后從中選擇前M個元素即可。 Java中現成的API可以使用:
    java.util.Collections.shuffle(List<?>)
    此算法非常簡單,循環N次,每次長度減少1,隨機獲取其中一個元素,然后交換其對稱元素。
    public static void shuffle(List<?> list, Random rnd) {
        int size = list.size();
        if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
            for (int i=size; i>1; i--)
                swap(list, i-1, rnd.nextInt(i));
        } else {
            Object arr[] = list.toArray();

            // Shuffle array
            for (int i=size; i>1; i--)
                swap(arr, i-1, rnd.nextInt(i));

            // Dump array back into list
            ListIterator it = list.listIterator();
            for (int i=0; i<arr.length; i++) {
                it.next();
                it.set(arr[i]);
            }
        }
    }

    有點意思的swap函數

    public static void swap(List<?> list, int i, int j) {
        final List l = list;
        l.set(i, l.set(j, l.get(i)));
    }

    其實我們的需求很簡單,在基本不變的集合中,多次重復隨機獲取其子集,至于子集是否有序或者隨機不重要的, 重要的是原集合中的每個元素都有相似的概率出現在子集合中。

    考慮到性能以及并發訪問(多線程)的需要,我想到了一個簡單的算法:
    給定N個元素集合,從中選擇M(0<M<=N)個元素的辦法是,
    1. 隨機選擇索引K(0<=K<N), i=0, 空子集
    2. 取有效元素N(k-i),N(k+i) 加入未滿子集M
    3. i+=1, 重復(2) 直到子集M已滿
    4. 終止
    這樣取出來的元素雖然和原始集順序有一定的關系,但是每個元素在子集里出現的概率相當,滿足結果要求。 最后生成的算法如下:
    public static <T> List<T> randomList(List<T> views, int max) {

        final int size = views.size();
        int index = RandomUtils.nextInt(size);
        //
        List<T> ret = new ArrayList<T>(max);
        int low = index - 1, high = index;
        while (max > 0 && (low >= 0 || high < size)) {
            if (low >= 0 && max-- > 0) {
                ret.add(views.get(low));
            }
            if (high < size && max-- > 0) {
                ret.add(views.get(high));
            }
            low--;
            high++;
        }
        return ret;
    }

    此算法滿足如下特點:
    1. 足夠快
    2. 線程安全(原始集合不變)
    3. 子元素出現概率相當(未經數學證明

    另外,stackoverflow上也有一些參考鏈接:

    [ 原文地址 http://imxylz.com/blog/2013/08/14/select-a-random-sublist-from-list-in-java/ ]


    ©2009-2014 IMXYLZ |求賢若渴
    posted on 2013-08-17 17:44 imxylz 閱讀(3851) 評論(3)  編輯  收藏 所屬分類: J2EE技術Java Concurrency

    評論

    # re: 隨機選擇集合的子元素集合 2013-08-22 16:43 hongliuliao
    如果允許改變views的話,我一般這么用
    views.remove(RandomUtils.nextInt(views.size()))
      回復  更多評論
      

    # re: 隨機選擇集合的子元素集合 2014-06-15 23:58 夢在飛
    真沒看出來哪線程安全了。
      回復  更多評論
      

    # re: 隨機選擇集合的子元素集合 2014-06-15 23:59 夢在飛
    能刪除嗎?發錯了,手機黨傷不起。@夢在飛
      回復  更多評論
      


    ©2009-2014 IMXYLZ
    主站蜘蛛池模板: 国产精品亚洲综合一区| 日本免费高清一本视频| 久久精品国产精品亚洲精品| 一级毛片免费在线观看网站| 免费大香伊蕉在人线国产| 在线播放亚洲精品| 亚洲成A人片在线观看无码3D| 婷婷国产偷v国产偷v亚洲| 亚洲国产一区视频| A毛片毛片看免费| 久久亚洲免费视频| 国拍在线精品视频免费观看| 亚洲一日韩欧美中文字幕在线| 午夜免费不卡毛片完整版| 最新亚洲人成网站在线观看| 亚洲午夜爱爱香蕉片| 国产啪精品视频网站免费尤物| 亚洲国产精品久久久久| 97在线观看永久免费视频| 亚洲乱人伦中文字幕无码| 亚洲精品无码久久久| 国产精品免费无遮挡无码永久视频| 亚洲精品高清视频| A级毛片内射免费视频| 羞羞视频免费网站含羞草| 国产亚洲3p无码一区二区| 4hu四虎最新免费地址| 国产亚洲综合视频| 亚洲人成在线电影| 国产极品粉嫩泬免费观看| 99精品视频免费| 国产精品久久亚洲不卡动漫| 亚洲AV无码乱码精品国产| 99精品视频在线免费观看| 亚洲人成色77777在线观看| 国产亚洲精久久久久久无码77777| 一级毛片在线免费观看| 亚洲AV成人无码网天堂| 亚洲国产精品国自产拍AV| 免费黄色一级毛片| 国产va在线观看免费|