" />

最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java數(shù)據(jù)隨機分頁實現(xiàn)方案

 更新時間:2023年06月16日 08:35:09   作者:壹米飯  
本文主要介紹了java數(shù)據(jù)隨機分頁實現(xiàn)方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

導語 | 網(wǎng)上搜到的方法,是使用數(shù)據(jù)庫的隨機排序ORDER BY RAND()進行的,較大數(shù)據(jù)的時候,顯然就不好使了,而且在數(shù)據(jù)庫層面進行隨機分頁就比較困難,無法保證基礎(chǔ)的有序性,因此需要考慮其他方法來進行實現(xiàn):數(shù)據(jù)庫+redis+List洗牌的方式就孕育而生。

問題產(chǎn)生

公司業(yè)務(wù)遇到此場景:在前端分頁展示數(shù)據(jù)時,為了讓每個數(shù)據(jù)都有相同的幾率被展示,每次分頁展示數(shù)據(jù)時,都是隨機展示的,并要求每一頁之間數(shù)據(jù)不能重復(fù);而且,優(yōu)先展示最近三天的上傳的數(shù)據(jù),用戶看完數(shù)據(jù)后,繼續(xù)加載三天前又三天的數(shù)據(jù)。

此時大概率會有一會有以下痛點:

  • 有用戶一直傳數(shù)據(jù),就會出現(xiàn)這個用戶數(shù)據(jù)占滿一頁;
  • 越晚上傳的數(shù)據(jù)曝光量會越好,越早上傳的數(shù)據(jù)曝光量越差;
  • 類似這種3天又3天數(shù)據(jù)如何加載?;

因此提出這個需求;數(shù)據(jù)需要隨機分頁出現(xiàn)。

問題分析與解決

分析一

遇到這種問題,單純的使用數(shù)據(jù)庫就不好使了,況且數(shù)據(jù)庫本身就比較脆弱;因此,我想到引入第三方工具:redis,而其我們軟件本身就使用redis;使用redis性能也會得到極大提升,主要用到redis list 的方法;

分析二

針對問題一,同一用戶數(shù)據(jù)占滿一頁,以及問題二的解決辦法;大腦跳出來的方法就是數(shù)據(jù)隨機選擇,這時我想到通過list洗牌的方法。

分析三

問題三,用戶看完數(shù)據(jù)后繼續(xù)加載后面的數(shù)據(jù),類似【懶加載】;解決辦法:當用戶刷數(shù)據(jù)到最后一頁的時候,就觸發(fā)【懶加載】,數(shù)據(jù)追加到redis list里面。
實現(xiàn)步驟與部分代碼

1. 查詢?nèi)斓臄?shù)據(jù),把主鍵id list 洗牌放入redis list;

// 使用 package java.util.Collections;
    /**
     * Randomly permutes the specified list using a default source of
     * randomness.  All permutations occur with approximately equal
     * likelihood.
     */
    public static void shuffle(List<?> list) {
        Random rnd = r;
        if (rnd == null)
            r = rnd = new Random(); // harmless race.
        shuffle(list, rnd);
    }
 /**
     * 追加Lisit
     *
     * @param key 關(guān)鍵字
     * @param list 列表
     * @param expireTime 有效期
     * @return boolean
     */
    public Boolean addAll(String key, List list, Long expireTime) {
        try {
            redisTemplate.opsForList().rightPushAll(key, list);
            redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
            return true;
        } catch (JedisException e) {
            handleJedisException(e);
            throw e;
        } finally {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        }
    }

這里需要注意,設(shè)置key的有效期;否則,你懂的?。?!

2.  觸發(fā)數(shù)據(jù)【懶加載】

/**
     * 構(gòu)建分頁數(shù)據(jù)
     * @param so 入?yún)?
     * @param key redis key
     * @param dayKey 天數(shù)區(qū)間的key
     * @return page
     */
    private IPage<PictureAlbumForUserDTO> buildPage(PublishedPictureAlbumSO so, String key, String dayKey) {
        Long total = redisUtil.listSize(key);
        long toIndex = so.getSize() * so.getPage();
        if (toIndex > total) { // 用戶加載到最后一頁,觸發(fā)【懶加載】
            // 發(fā)現(xiàn)池,加載更多數(shù)據(jù)
            String dayValue = redisUtil.get(dayKey);
            String[] dayValueArray = dayValue.split("#");
            long start = Long.parseLong(dayValueArray[0]) - rangeDay;
            long end = Long.parseLong(dayValueArray[1]) - rangeDay;
            if (appendList(key, dayKey, start, end)) {
                // 遞歸調(diào)用;遞歸后,數(shù)據(jù)追加到redis
                return buildPage(so, key, dayKey);
            } else {
                toIndex = total;
            }
        }
        // 根據(jù)下標獲取redis里面分頁數(shù)據(jù)
        List list = redisUtil.listRange(key, so.getSize() * (so.getPage() - 1), toIndex);
        if (CollectionUtil.isEmpty(list)) {
            return null;
        }
        so.setAlbumIdList(list);
        // 因為進行l(wèi)ist id 分頁,這里默認去數(shù)據(jù)庫里查詢第一頁就行了
        so.setPage(1);
        Page<PictureAlbumForUserDTO> pageData = new Page<>(so.getPage(), so.getSize());
        IPage<PictureAlbumForUserDTO> iPage = baseMapper.findAllActive(pageData, so);
        List<PictureAlbumForUserDTO> dtoList = iPage.getRecords();
        Collections.shuffle(dtoList);
        iPage.setRecords(dtoList);
        iPage.setTotal(total);
        iPage.setSize(so.getSize());
        iPage.setCurrent(so.getPage());
        iPage.setPages((total + so.getSize() - 1) / so.getSize());
        return iPage;
    }
 /**
     * 讀取redis lisit 區(qū)間數(shù)據(jù)
     *
     * @param key 關(guān)鍵字
     * @param start 開始下標
     * @param end 結(jié)束下標
     * @return boolean
     */
    public List listRange(String key, long start, long end) {
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (JedisException e) {
            handleJedisException(e);
            throw e;
        } finally {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        }
    }

3. 每頁數(shù)據(jù)隨機展示

如何想讓用戶每一頁看到的數(shù)據(jù)不一樣;分頁的數(shù)據(jù)可以再進行洗牌,而且不會打亂數(shù)據(jù)池整體的數(shù)據(jù)排列,有種【千人千面】的錯覺;缺點就是用戶可能會覺得,你的分頁數(shù)據(jù)存在問題。

總結(jié)

介紹了一種實現(xiàn)隨機分頁的方案,關(guān)鍵在與數(shù)據(jù)庫結(jié)合redis的使用和list的洗牌,這種方法從效率和使用性性都比較高的;對付萬級核心數(shù)據(jù)的隨機分頁,應(yīng)該是沒有問題的。

到此這篇關(guān)于java數(shù)據(jù)隨機分頁實現(xiàn)方案的文章就介紹到這了,更多相關(guān)java數(shù)據(jù)隨機分頁內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

贵港市| 临沭县| 五指山市| 长宁区| 双流县| 阿鲁科尔沁旗| 拉萨市| 高台县| 布尔津县| 安顺市| 灵台县| 江安县| 祁阳县| 邓州市| 怀化市| 广安市| 上蔡县| 平阳县| 南通市| 焉耆| 偃师市| 抚州市| 手机| 巴南区| 泗洪县| 永胜县| 南康市| 乌审旗| 曲松县| 县级市| 彩票| 陕西省| 盐城市| 岑溪市| 靖州| 盐城市| 沈丘县| 康马县| 盐池县| 昌图县| 饶平县|