成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Java 中實(shí)現(xiàn)集合的 keep in order (后續(xù))

loostudy / 1815人閱讀

摘要:寫(xiě)完上一篇中實(shí)現(xiàn)集合的后,自己又進(jìn)行了一番探索,結(jié)合在公司項(xiàng)目的實(shí)際測(cè)試后,總結(jié)了一個(gè)更加有效地基于紅黑樹(shù)的結(jié)構(gòu)來(lái)實(shí)現(xiàn)集合的,由于使用二叉樹(shù)來(lái)保存有序集合,因此對(duì)集合的增加刪除查找的時(shí)間復(fù)雜度均為。

寫(xiě)完上一篇「Java 中實(shí)現(xiàn)集合的 keep in order」后,自己又進(jìn)行了一番探索,結(jié)合在公司項(xiàng)目的實(shí)際測(cè)試后,總結(jié)了一個(gè)更加有效地、基于 TreeSet(紅黑樹(shù))的結(jié)構(gòu)來(lái)實(shí)現(xiàn)集合的 keep in order,由于使用二叉樹(shù)來(lái)保存有序集合,因此對(duì)集合的增加、刪除、查找的時(shí)間復(fù)雜度均為 log(n)

集合(Set)的約定

Java 中對(duì)集合(Set)一般做法是:為了代碼的健壯性,盡量在 Set 中保存不可變的對(duì)象。因?yàn)椴还苁?HashSet 還是 TreeSet,他們都依賴元素自身的特性來(lái)保證集合的不重復(fù)性。如 HashSet 依賴元素的 equalshashCode 方法,TreeSet 依賴元素的 compareTo 方法或自定義的 Comparator。

元素改變情況下保持集合有序

首先,公司項(xiàng)目里,服務(wù)器維護(hù)了一個(gè)玩家的集合:

class PlayerManager {
    
    // 玩家的 Map,<玩家 id -> 玩家實(shí)體>
    Map map = new ConcurrentHashMap<>();
}

// 玩家實(shí)體
interface Player {
    
    int getId();
    
    int getMoney();
    
    void setMoney(int money);
}

這個(gè) map 將成為數(shù)據(jù)源,它不一定是有序。現(xiàn)在增加一個(gè)成員:

// 可重排序的集合,保存不可變對(duì)象:玩家 id
Set reorderableSet;

這個(gè)集合記錄這所有玩家的 id 值,并以某種順序進(jìn)行排序,排序的規(guī)則視需求而定,假如要以玩家擁有的金錢數(shù)來(lái)做財(cái)富排行榜。
由于玩家的財(cái)富值始終在發(fā)生變化,因此我定義一個(gè)接口來(lái)感知這種變化:

interface Reorderable {

    // 這個(gè)方法用于重新計(jì)算元素 E 在集合中的索引
    void recomputeOrder(E element, ElementChangedCallback callback);

    // 這是一個(gè)回調(diào),處理元素值改變的代碼
    interface ElementChangedCallback {

        void onElementChanged(E element);
    }
}

然后用 TreeSet 的子類實(shí)現(xiàn)上面的 Reorderable 接口來(lái)構(gòu)造一個(gè)可重排序的集合:

class ReorderableSet extends TreeSet implements Reorderable {

    // 使用自定義的比較器
    public ReorderableSet(Comparator comparator) {
        super(comparator);
    }

    @Override
    public void recomputeOrder(E element, ElementChangedCallback callback) {
        if (contains(element)) {
            // 先將元素從集合中移除,時(shí)間復(fù)雜度 log(n)
            remove(element);
            // 再使用回調(diào)去改變?cè)氐闹?            callback.onElementChanged(element);
            // 在將元素添加到集合里,時(shí)間復(fù)雜度 log(n)
            add(element);
        }
    }
}

因?yàn)槭菍?shí)現(xiàn)一個(gè)財(cái)富排行榜,所以定義排序規(guī)則為簡(jiǎn)單的比較一下金錢數(shù)目即可:

// 這里的 Integer 代表玩家 id
class MoneyComparator implements Comparator {

    @Override
    public int compare(Integer A, Integer B) {
        
        // 從服務(wù)器維護(hù)的玩家集合中獲取玩家的引用
        Player playerA = map.get(A);
        Player playerB = map.get(B);
        
        // 降序排列
        return playerB.getMoney() - playerA.getMoney();
    }
}

這時(shí)候可以構(gòu)造之前定義的 Set reorderableSet 了:

Set reorderableSet = new ReorderableSet<>(new MoneyComparator());

要響應(yīng)玩家金錢的變化,則構(gòu)造一個(gè)實(shí)現(xiàn) ElementChangedCallback 接口的類,并把它放在任何玩家金錢改變的地方:

class UpdateMoney implements Reorderable.ElementChangedCallback {

    int money;

    UpdateMoney(int money) {
        this.money= money;
    }

    @Override
    public void onElementChanged(Integer playerId) {
        // 玩家金錢改變
        Player player = map.get(playerId);
        player.setMoney(money);
    }
}

玩家金錢改變的時(shí)候調(diào)用一下代碼,比如買東西的時(shí)候

void buyGood(Player player, int cost) {
    Reorderable reorderableSet = ......; // 獲得引用
    int moneyRemain = player.getMoney() - cost;
    
    // 構(gòu)造 UpdateMoney 回調(diào)
    reorderableSet .recomputeOrder(player.getId(), new UpdateMoney(moneyRemain);
}

因此,就可以實(shí)現(xiàn)集合(Set)在元素值改變時(shí)保持有序了,由于 TreeSet 基于紅黑樹(shù)實(shí)現(xiàn),對(duì)它的查找添加刪除均很快。

總結(jié)

通用的框架就像下面這樣:

class ReorderableSet extends TreeSet implements Reorderable {

    public ReorderableSet() {
    }

    public ReorderableSet(Comparator comparator) {
        super(comparator);
    }

    public ReorderableSet(Collection c) {
        super(c);
    }

    public ReorderableSet(SortedSet s) {
        super(s);
    }

    @Override
    public void recomputeOrder(E element, ElementChangedCallback callback) {
        if (contains(element)) {
            // 先將元素從集合中移除,時(shí)間復(fù)雜度 log(n)
            remove(element);
            // 再使用回調(diào)去改變?cè)氐闹?            callback.onElementChanged(element);
            // 在將元素添加到集合里,時(shí)間復(fù)雜度 log(n)
            add(element);
        }
    }
}

interface Reorderable {

    void recomputeOrder(E element, ElementChangedCallback callback);

    interface ElementChangedCallback {

        void onElementChanged(E element);
    }
}

考慮到線程安全,可以在 recomputeOrder 中進(jìn)行加鎖操作。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/65812.html

相關(guān)文章

  • Java 中實(shí)現(xiàn)集合 keep in order

    摘要:此項(xiàng)禁止的一個(gè)特殊情況是不允許某個(gè)包含其自身作為元素。即使的順序與不一致,其行為也是定義良好的它只是違背了接口的常規(guī)協(xié)定。 原問(wèn)題 Java 中怎樣實(shí)現(xiàn)一種即使元素改變依然有序的集合? 問(wèn)題由來(lái) 起因是在公司做游戲項(xiàng)目的時(shí)候遇到一個(gè)需求需要實(shí)現(xiàn): 服務(wù)器要維護(hù)一個(gè)幫派成員(Member)的集合,這個(gè)集合要按照在線狀態(tài)、成員等級(jí)和名稱依次有序排列。 由于每時(shí)每刻都有玩家在不斷上下線,成員...

    gyl_coder 評(píng)論0 收藏0
  • Spring核心接口之Ordered

    摘要:一接口介紹中提供了一個(gè)接口。從單詞意思就知道接口的作用就是用來(lái)排序的。類實(shí)現(xiàn)了接口的一個(gè)比較器。三中使用接口在的例子在配置文件中添加,那么默認(rèn)會(huì)注入和這兩個(gè)類。 一、Ordered接口介紹Spring中提供了一個(gè)Ordered接口。從單詞意思就知道Ordered接口的作用就是用來(lái)排序的。Spring框架是一個(gè)大量使用策略設(shè)計(jì)模式的框架,這意味著有很多相同接口的實(shí)現(xiàn)類,那么必定會(huì)有優(yōu)先級(jí)...

    cartoon 評(píng)論0 收藏0
  • LinkedHashMap 源碼詳細(xì)分析(JDK1.8)

    摘要:關(guān)于的源碼分析,本文并不打算展開(kāi)講了。大家可以參考我之前的一篇文章源碼詳細(xì)分析。在刪除節(jié)點(diǎn)時(shí),父類的刪除邏輯并不會(huì)修復(fù)所維護(hù)的雙向鏈表,這不是它的職責(zé)。在節(jié)分析鏈表建立過(guò)程時(shí),我故意忽略了部分源碼分析。 1. 概述 LinkedHashMap 繼承自 HashMap,在 HashMap 基礎(chǔ)上,通過(guò)維護(hù)一條雙向鏈表,解決了 HashMap 不能隨時(shí)保持遍歷順序和插入順序一致的問(wèn)題。除此...

    Harriet666 評(píng)論0 收藏0
  • 基于LinkedBlockingQueue實(shí)現(xiàn)股票交易系統(tǒng)

    摘要:與基于數(shù)組的隊(duì)列相同,重載的構(gòu)造函數(shù)可以接受集合指定的初始值。這種隊(duì)列比基于數(shù)組阻塞隊(duì)列具有更高的吞吐量。創(chuàng)建個(gè)交易者實(shí)例,將自己出售的訂單放入隊(duì)列中,每個(gè)出售訂單都將會(huì)有隨機(jī)的交易量。要使用基于優(yōu)先級(jí)的隊(duì)列,需要提供適當(dāng)?shù)谋容^器。 阻塞隊(duì)列 在阻塞隊(duì)列的幫助下,許多同步問(wèn)題都可以被公式化。阻塞隊(duì)列是隊(duì)列,當(dāng)線程試圖對(duì)空隊(duì)列進(jìn)行出列操作,或試圖向滿的隊(duì)列中插入條目時(shí),隊(duì)列就會(huì)阻塞。直到...

    30e8336b8229 評(píng)論0 收藏0
  • Java? 教程(高級(jí)并發(fā)對(duì)象)

    高級(jí)并發(fā)對(duì)象 到目前為止,本課程重點(diǎn)關(guān)注從一開(kāi)始就是Java平臺(tái)一部分的低級(jí)別API,這些API適用于非?;A(chǔ)的任務(wù),但更高級(jí)的任務(wù)需要更高級(jí)別的構(gòu)建塊,對(duì)于充分利用當(dāng)今多處理器和多核系統(tǒng)的大規(guī)模并發(fā)應(yīng)用程序尤其如此。 在本節(jié)中,我們將介紹Java平臺(tái)5.0版中引入的一些高級(jí)并發(fā)功能,大多數(shù)這些功能都在新的java.util.concurrent包中實(shí)現(xiàn),Java集合框架中還有新的并發(fā)數(shù)據(jù)結(jié)構(gòu)。 ...

    xiaotianyi 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<