是否有任何数据结构可以保留迭代顺序并丢弃旧记录?

时间:2017-01-20 00:13:59

标签: java data-structures guava

我有一个用例,我希望将条目填充到多个线程的数据结构中,因此它必须是线程安全的,并且在达到特定大小后开始丢弃旧记录。我还想以与Insertion相同的顺序迭代数据结构。

所以我决定在这里使用Guava Cache,但令我惊讶的是,Guava asMap()方法不会以任何特定的顺序返回元素。

private final Cache<Integer, Integer> cache =
      CacheBuilder.newBuilder().maximumSize(10)
          .removalListener(
              RemovalListeners.asynchronous(new CustomListener(), executorService)
          ).build();

cache.put(1, 1);
cache.put(2, 2);
cache.put(3, 3);
cache.put(4, 4);
cache.put(5, 5);
cache.put(6, 6);

for (Entry<Integer, Integer> entry : cache.asMap().entrySet()) {
  System.out.println(entry.getKey() + "=" + entry.getValue());
}

输出:

2=2
6=6
1=1
4=4
3=3
5=5

我可以在这里使用哪些其他有效的数据结构,可以保留我的迭代顺序,并且可靠一旦达到大小就删除旧记录并对删除侦听器进行一些回调可以弄清楚哪些记录被删除了?

任何例子都会有很大的帮助。我使用的是Java 7,但还是无法切换到Java 8。

所以我应该能够在迭代时得到这样的东西,并且它应该自动删除旧记录:

1=1
2=2
3=3
4=4
5=5
6=6

4 个答案:

答案 0 :(得分:1)

对于Java 7,您可以使用Caffeine的前身ConcurrentLinkedHashMap

ConcurrentMap<Integer, Integer> cache =
        new ConcurrentLinkedHashMap.Builder<Integer, Integer>()
                .maximumWeightedCapacity(10)
                .build();

cache.put(1, 1);
cache.put(2, 2);
cache.put(3, 3);
cache.put(4, 4);
cache.put(5, 5);
cache.put(6, 6);

for (Entry<Integer, Integer> entry : cache.entrySet()) {
    System.out.println(entry.getKey() + "=" + entry.getValue());
}

<强>输出

1=1
2=2
3=3
4=4
5=5
6=6

有关详细信息,请参阅ExampleUsage · ben-manes/concurrentlinkedhashmap Wiki

答案 1 :(得分:0)

保留迭代顺序的公共数据结构是

  • 队列
  • deque
  • 链表等..

然而,最适合您需求的解决方案是使用 deque ,它提供了一些内置函数,例如,

add(element):向尾部添加一个元素。

addFirst(element):向头部添加元素。

addLast(element):向尾部添加一个元素。

offer(element):向尾部添加一个元素并返回一个布尔值来解释插入是否成功。

offerFirst(element):向头部添加一个元素并返回一个布尔值 解释插入是否成功。

offerLast(element):向尾部添加一个元素并返回一个布尔值来解释插入是否成功。

iterator():返回此双端队列的迭代器。

descendingIterator():返回一个迭代器,该迭代器与此双端队列的顺序相反。

push(element):向头部添加元素。

pop(element):从头部移除一个元素并将其返回。

removeFirst():删除头部的元素。

removeLast():删除尾部的元素。

有关deque的更多信息:https://examples.javacodegeeks.com/core-java/util/deque-util/java-util-deque-example/

答案 2 :(得分:0)

鉴于您在示例中显示put(k, v),我假设您也将此数据结构用于基于键的查找,因此简单的队列并不理想。

在这种情况下,您可以使用LikedHashMap包裹的Collection.synchronized,并实施removeEldest方法。以下示例不显示多个线程,但应该可以正常使用多个线程。为了对要删除的项目执行您自己的计算,您在entryRemoved的子类中实现BoundedMap方法:

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Collections;

class BoundedMap<K, V> extends LinkedHashMap<K, V> {
  private final int capacity;

  public BoundedMap(int capacity) {
    this.capacity = capacity;
  }

  @Override
  protected boolean removeEldestEntry(Map.Entry<K, V> eldest){
    if(size() > capacity) {
      remove(eldest.getKey());
      entryRemoved(eldest);
    }
    return false;
  }

  public void entryRemoved(Map.Entry<K,V> entry) {
  }
}

public class Test {
  public static void main(String[] args) {
    Map<Integer, Integer> m = Collections.synchronizedMap(
      new BoundedMap<Integer, Integer>(5) {
        @Override
        public void entryRemoved(Map.Entry entry) {
          System.out.println(entry);
        }
    });
    System.out.println("--- adding");
    for (int i=0; i<8; i++) {
      m.put(i, -i);
    }
    System.out.println("-- iterating");
    for(Map.Entry<Integer, Integer> entry : m.entrySet()) {
      System.out.println(entry);
    }
  }
}

答案 3 :(得分:0)

您可以通过覆盖$.get(endereco + "&acao=teste&" + formulario, function(data) { alert(data); }); 的{​​{1}}的简单子类来执行此操作,如Javadoc中所述。