<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 閱讀(3862) 評論(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
    主站蜘蛛池模板: 精品国产一区二区三区免费| 亚洲丶国产丶欧美一区二区三区| 国产精品免费久久| 亚洲婷婷综合色高清在线| 伊人免费在线观看高清版| 夜夜春亚洲嫩草影院| 国产免费内射又粗又爽密桃视频| 国产精品亚洲产品一区二区三区 | 亚洲人成网站999久久久综合| 成人午夜免费福利视频| 亚洲毛片基地4455ww| 毛色毛片免费观看| 亚洲欧洲自拍拍偷午夜色无码| 精选影视免费在线 | 久久亚洲国产午夜精品理论片| 一区二区三区无码视频免费福利| 最新中文字幕电影免费观看| 亚洲人成色4444在线观看| 国产高清免费观看| 免费一级毛片在线播放视频免费观看永久| 免费国产在线观看| 精品人妻系列无码人妻免费视频| 国产亚洲成AV人片在线观黄桃 | 日韩精品无码区免费专区| 亚洲人成色777777老人头| 亚洲国产午夜中文字幕精品黄网站 | 免费的黄色的网站| 国产亚洲3p无码一区二区| 无码国产精品一区二区免费vr| 亚洲视频在线观看网站| 免费黄色一级毛片| 好湿好大好紧好爽免费视频| 337p日本欧洲亚洲大胆艺术| 手机在线毛片免费播放| kk4kk免费视频毛片| 亚洲成人福利在线观看| 国产自产拍精品视频免费看| 黄色免费在线网站| 亚洲色偷偷综合亚洲av78| 中文亚洲AV片不卡在线观看| 222www免费视频|