2016-06-23 11 views
3

マップとリストの2つのコレクションで参照を共有しようとしています。私は両方のコレクションにプッシュし、リストの後ろから削除して、マップからも削除したいと思います。このコードは、私がやりたいことを提示する単なるサンプルであり、コンパイルさえしません!2つのコレクションで参照変数を共有

これを実装するための正しいパラダイムは何ですか?どのような保証がベストプラクティスですか?

use std::collections::{HashMap, LinkedList}; 

struct Data { 
    url: String, 
    access: u64, 
} 

struct Holder { 
    list: LinkedList<Box<Data>>, 
    map: HashMap<String, Box<Data>>, 
} 

impl Holder { 
    fn push(&mut self, d: Data) { 
     let boxed = Box::new(d); 
     self.list.push_back(boxed); 
     self.map.insert(d.url.to_owned(), boxed); 
    } 

    fn remove_last(&mut self) { 
     if let Some(v) = self.list.back() { 
      self.map.remove(&v.url); 
     } 
     self.list.pop_back(); 
    } 
} 

答えて

2

複数のコレクション内の単一アイテムを格納する考えは同時に新しいものではありません...と単純ではありません。

共有要素に共通の考えがどちらかでありますそれは安全ではない(コレクションが何本あるかを知っている)共有ポインタ。

いくつかの非効率性は、やみくもに共有ポインタで定期的なコレクションを使用してあります:ノードベースのコレクションは、あなたが他の1つのビューからの切り替えダブル間接

  • は、すべての要素を見つける必要持つ意味

    • 上に戻る

    Boost.MultiIndex(C++)では、値をラップしてこのノードをさまざまなビューにリンクするための介入ノードを作成するというパラダイムが使用されています。このトリック(と難しさ)は、O(1)またはO(log N)内でそれを「リンク解除」できるように周囲の要素に到達できるように、侵入型ノードを作成することです。

    かなりの時間を費やす準備ができていない限り、試してみることをお勧めしません。

    このように、迅速な解決のために:

    type Node = Rc<RefCell<Data>>; 
    
    struct Holder { 
        list: LinkedList<Node>, 
        map: HashMap<String, Node>, 
    } 
    

    限り、あなたはurlで削除する必要はありませんように、これは十分に効率的です。


    コンプリート例:

    use std::collections::{HashMap, LinkedList}; 
    use std::cell::RefCell; 
    use std::rc::Rc; 
    
    struct Data { 
        url: String, 
        access: u64, 
    } 
    
    type Node = Rc<RefCell<Data>>; 
    
    struct Holder { 
        list: LinkedList<Node>, 
        map: HashMap<String, Node>, 
    } 
    
    impl Holder { 
        fn push(&mut self, d: Data) { 
         let url = d.url.to_owned(); 
         let node = Rc::new(RefCell::new(d)); 
         self.list.push_back(Rc::clone(&node)); 
         self.map.insert(url, node); 
        } 
    
        fn remove_last(&mut self) { 
         if let Some(node) = self.list.back() { 
          self.map.remove(&node.borrow().url); 
         } 
         self.list.pop_back(); 
        } 
    } 
    
    fn main() {} 
    
  • +0

    'RefCell'の性能上の問題は、アイテムに' RWLock'があることがわかっているので、どうでしょうか?巨額のデータでそれほど悪くないのですか? –

    +2

    @NavidNabavi意味的にはRWLockのように、多くの読者が許可されているが、ライターは1人だけです。しかし、ロックとは異なり、スレッド間で作業する必要はありません。したがって、変更可能な参照を取得することは、文字通り通常の非アトミックメモリアクセス(実際にアクセスできるように、アクセスするデータの近く)および条件付きジャンプです。これは安価ですが、唯一の潜在的な減速は、キャッシュを傷つける可能性のある追加のメモリを必要とするためです。しかし、それをベンチマークして自分自身で見てみませんか? – delnan

    1

    個人的に、私はRcの代わりBoxを使用します。

    代わりに、すなわち代わりHashMap<String, Box<Data>>HashMap<String, usize>を使用します(あなたのハッシュマップの値型としてあなたのリストへのインデックスを格納することができます。

    あなたがやろうとしている内容に応じて、それだけには良いアイデアかもしれません両方のリストやマップのいずれかを持って、そしてません。

    +0

    私は値を文字列でアクセスし、リストで削除する必要があります。このため、パフォーマンスを向上させるためには両方を使用する必要があります。そして私はmutablityかもしれない別のキーが必要です。 –

    +0

    マップとリストの両方ではなくマップのみを使用すると、ここで実際に実行しようとしているものよりもパフォーマンスが向上します。 – Adrian

    +0

    私は挿入して私のデータのシーケンスを失います。 –

    関連する問題