<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
    主站蜘蛛池模板: 一个人看的在线免费视频| 亚洲色欲www综合网| 免费一级肉体全黄毛片| 日韩中文字幕在线免费观看 | 亚洲精品一卡2卡3卡三卡四卡| 亚洲第一精品福利| 亚洲AV日韩AV天堂久久| 亚洲一区二区中文| 亚洲精品中文字幕麻豆| 色天使亚洲综合在线观看| 亚洲国产系列一区二区三区| 亚洲欧洲国产综合AV无码久久| 亚洲无人区码一二三码区别图片| 亚洲精品无码久久| 国产亚洲精彩视频| 一区二区三区AV高清免费波多| 国产男女爽爽爽免费视频 | 久久综合亚洲色hezyo| 欧洲乱码伦视频免费国产| 久久久久久99av无码免费网站 | 三级毛片在线免费观看| 国产精品免费福利久久| 在线看片韩国免费人成视频| 成人毛片18女人毛片免费视频未| 国产又粗又长又硬免费视频| 久久久久亚洲AV成人网人人网站| 亚洲av无码av制服另类专区| 亚洲国产成人久久77| 亚洲aⅴ无码专区在线观看春色| 一级毛片一级毛片免费毛片| 久久狠狠躁免费观看| 毛片a级三毛片免费播放| 亚洲av再在线观看| 亚洲精品成人av在线| 亚洲综合激情五月丁香六月| 精品国产亚洲一区二区三区在线观看 | 国产成人毛片亚洲精品| 亚洲日本一区二区| 亚洲精品天堂无码中文字幕| 99re6在线精品免费观看| 97免费人妻无码视频|