【问题标题】:Ordered (natural insertion order) and threadsafe Java Map有序(自然插入顺序)和线程安全的 Java Map
【发布时间】:2013-05-26 00:09:22
【问题描述】:

我有一个遗留应用程序,他们在其中使用 ConcurrentHashMap。现在我们知道 concurrentHasMap 是无序的,但是读取最初插入的对象是必需的。我已经在生产中使用了一段时间的代码,因此我正在寻找快速替代品来替换集合,这也可以让我订购。基本上是在寻找一种非常非侵入性的解决方案,它可以最大限度地减少代码更改。我在网上搜索并获得了 ConcurrentSkipListMap 作为替代方案,但它对我不起作用。原因是,默认情况下,它按密钥的自然顺序排序,这对我不起作用。由于我的键是字符串,我需要根据插入进行排序,而不是字符串键在地图中的自然排序方式。

请尽早提出一些替代方案。

谢谢 阿努巴夫

【问题讨论】:

标签: java multithreading map java.util.concurrent


【解决方案1】:

您应该能够使用LinkedHashMap 来保留插入顺序,并使用Collections.synchronizedMap(Map map) 方法使其成为synchronized

public class Test {
  Map<String, String> map = new LinkedHashMap<>();
  Map<String, String> test = Collections.synchronizedMap(map);

  public void test() {
    test.put("Z", "Zed");
    test.put("A", "Ay");
    for (String s : test.keySet()) {
      System.out.println(s);
    }
  }

  public static void main(String args[]) {
    try {
      new Test().test();
    } catch (Throwable t) {
      t.printStackTrace(System.err);
    }
  }

}

打印出来:

Z
A

如您所愿。

【讨论】:

  • 这是一个重大的变化 - 迭代需要同步,并且 CHM 特定的方法(例如 putIfAbsent)不会被轻易替换。
  • @assylias - 同意 - 这只有在 OP 不使用这些方法时才有效。
【解决方案2】:

您可以自己重新排序密钥。这样的事情可能是可能的。请注意,这不是一个完整的解决方案,要正确实施ConcurrentMap,还需要做很多额外的工作。

class InsertOrderedMap<K, V> implements ConcurrentMap<K,V> {
  // The actual map holding the data.
  Map<Integer, V> ordered = new ConcurrentSkipListMap<>();
  // Mapping the key to the order.
  Map<K, Integer> reorder = new ConcurrentSkipListMap<>();
  // The next position.
  AtomicInteger next = new AtomicInteger(0);

  @Override
  public V get(Object o) {
    return ordered.get(reorder.get(o));
  }

}

如果您向同一个键添加两次,您必须决定需要发生什么。值应该在哪个位置,原始位置还是新位置?是否应该删除原始的?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-24
    • 1970-01-01
    • 2023-02-23
    • 2010-10-15
    • 1970-01-01
    • 2019-06-01
    • 2015-11-14
    • 2013-02-10
    相关资源
    最近更新 更多