Safe and efficient way to use String and its pointer in different collections

|▌冷眼眸甩不掉的悲伤 提交于 2021-02-08 06:46:15

问题


  • I have a bunch of long immutable strings, which I would like to store in a HashSet.
  • I need a bunch of mappings with these strings as keys.
  • I would like to use references to these strings as keys in these mappings to avoid copying strings.

This is how I managed to eventually get to this status. The only concern is this extra copy I need to make at line 5.

let mut strings: HashSet<String> = HashSet::new();  // 1
let mut map: HashMap<&String, u8> = HashMap::new(); // 2
                                                    // 3
let s = "very long string".to_string();             // 4
strings.insert(s.clone());                          // 5
let s_ref = strings.get(&s).unwrap();               // 6
map.insert(s_ref, 5);                               // 7

playground link

To avoid this cloning I found two workarounds:

  • Use Rc for string (adds overhead and code clutter)
  • Use unsafe code

Is there any sensible way to remove this excessive cloning?


回答1:


It seems to me that what you are looking for is String Interning. There is a library, string-cache, which was developed as part of the Servo project which may be of help.

In any case, the basics are simple:

  • a long-lived pool of String, which guarantees they will not be moving at all
  • a look-up system to avoid inserting duplicates in the pool

You can use a typed arena to store your String, and then store &str to those strings without copying them (they will live for as long as the arena lives). Use a HashSet<&str> on top to avoid duplicates, and you're set.



来源:https://stackoverflow.com/questions/39205905/safe-and-efficient-way-to-use-string-and-its-pointer-in-different-collections

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!