Collector.toMap с использованием дженериков - PullRequest
3 голосов
/ 11 апреля 2020

Мне трудно использовать потоковый API в Java для универсальной карты. У меня есть карта, которая расширяет LinkedHashMap следующим образом

public class LRUCache<K, V> extends LinkedHashMap<K, V> {
  private int size;

  public LRUCache(int size) {
    super(size);
    this.size = size;
  }

  @Override
  protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
    return size() > size;
  }

  public LRUCache<K, V> collect() {
    return entrySet()
        .stream()
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)
    );
  }

}

Я экспериментирую с фиктивным методом collect, который на самом деле будет передавать поток на entrySet, применить к нему некоторые фильтры и затем вернуть новый LRUCache, но Collectors.toMap продолжайте выдавать ошибку, которая говорит

«Нестатистический c метод не может быть вызван из статического c контекста»

Я знаю, что это некоторая проблема с коллектором. Определение универсальных карт. Но я не могу найти правильные дженерики, чтобы избавиться от ошибки и достичь функциональности потоковой передачи и сбора

Ответы [ 2 ]

3 голосов
/ 11 апреля 2020

LinkedHashMap включает в свою реализацию конструктор без аргументов, который действует как поставщик для операции toMap collect . Вы можете ввести то же самое, включив:

public LRUCache() {
    this(10); // default size
}

После этого вы можете собрать реализацию LRUCache, используя переопределение toMap с поставщиком LRUCache::new, следующим образом:

public LRUCache<K, V> collect() {
    return entrySet().stream()
            .collect(Collectors.toMap(Map.Entry::getKey,
                    Map.Entry::getValue, 
                    (a, b) -> a, LRUCache::new));
}

Примечание: - То, что имеет значение, - это предоставление поставщику данных для реализации, отличной от HashMap, то есть то, что вы получаете, используя другую перегруженную реализацию toMap.

2 голосов
/ 11 апреля 2020

Вы просто пытаетесь скопировать вашу карту / кеш. Для этого нет необходимости в потоках.

Добавьте (возможно частный) конструктор, который вызывает конструктор копирования карты:

private LRUCache(Map<K, V> map, int size) {
  super(map);
  this.size = size;
}

Затем просто используйте это в своем методе сбора:

public LRUCache<K, V> collect() {
  return new LRUCache<>(this, size);
}

Или без добавления конструктора:

public LRUCache<K, V> collect() {    
  LRUCache<K, V> copy = new LRUCache<>(size);
  copy.putAll(this);
  return copy;
}
...