<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
    主站蜘蛛池模板: 免费国产美女爽到喷出水来视频| 57pao国产成视频免费播放 | 亚洲人成人77777在线播放| 特级做A爰片毛片免费看无码| 亚洲成av人片不卡无码久久| 亚洲AV无码XXX麻豆艾秋| 毛片a级三毛片免费播放| 7777久久亚洲中文字幕| 无码高潮少妇毛多水多水免费| 亚洲一区二区三区免费在线观看| 2019中文字幕免费电影在线播放| 91久久亚洲国产成人精品性色| 蜜臀AV免费一区二区三区| 亚洲已满18点击进入在线观看| 曰批全过程免费视频在线观看 | 97人伦色伦成人免费视频| 亚洲偷偷自拍高清| 精品无码国产污污污免费| 日本亚洲欧美色视频在线播放| 免费国产在线观看老王影院| 一级毛片免费在线观看网站| 亚洲最大激情中文字幕| 免费人成视频在线观看网站| 亚洲剧场午夜在线观看| 日韩高清免费在线观看| 日亚毛片免费乱码不卡一区| 国产AV无码专区亚洲AVJULIA| 2021国内精品久久久久精免费| 亚洲最大中文字幕无码网站| 亚洲成A人片在线观看无码3D| 97在线视频免费公开视频| 亚洲成人动漫在线观看| 毛片基地免费观看| 一级中文字幕乱码免费| 中文字幕亚洲综合久久| 麻豆国产人免费人成免费视频| 国产高清对白在线观看免费91| 亚洲精品中文字幕乱码影院| 免费国产不卡午夜福在线| 国偷自产一区二区免费视频| 亚洲精品国产日韩|