У меня есть SortedSet<MyObject> и MyObject есть логика compareTo для Date.

class MyObject {
   .. many fields
   private Date date;

   @Override
    public int compareTo(MyObject object) {
    .. logic here..
    }    

}

Я хочу преобразовать этот SortedSet в TreeMap или Guava ImmutableSortedMap с ключами в качестве позиций элемента в SortedSet.

Например

0 -> MyObject1
1 -> MyObject2
...and so on

Я могу перебирать SortedSet и вручную помещать элементы в новый TreeMap, но мне было интересно, есть ли более чистый способ сделать это через Streams или библиотеки Guava / библиотеку Collection.

0
Novice User 26 Окт 2019 в 00:22
2
Обратите внимание, что карта, индексированная непрерывными целочисленными ключами от нуля, фактически является List. Итак, ImmutableList.copyOf(yourSet) может работать.
 – 
Andy Turner
26 Окт 2019 в 00:26
Реализует ли ваш класс Comparable?
 – 
Bohemian♦
26 Окт 2019 в 00:34
Да, он реализует Comparable<MyObject>
 – 
Novice User
26 Окт 2019 в 00:35
Я не понимаю этого with keys as positions of keys
 – 
Deadpool
26 Окт 2019 в 00:37
Извините, я имел в виду положение элемента в SortedSet
 – 
Novice User
26 Окт 2019 в 00:38

3 ответа

Просто сделайте это с помощью петли.

TreeMap<Integer, MyClass> map = new TreeMap<>();
for (MyClass myClass : sortedSet) {
  map.put(map.size(), myClass);
}

Я считаю, что это намного яснее, чем подход потоков, предложенный Bohemian.

2
Andy Turner 27 Окт 2019 в 20:36
… И если вы хотите любой ценой использовать лямбды, вы все равно можете использовать sortedSet.forEach(item -> map.put(map.size(), item));
 – 
Holger
28 Окт 2019 в 17:35

Разве ваша TreeMap не представляет себе, каким будет массив?

MyObject[] myObjects = sortedMap.toArray();
0
fedup 26 Окт 2019 в 00:42
Да, это вроде как сейчас, но я предпочитаю TreeMap, поскольку он не растет, как List, из-за индекса.
 – 
Novice User
26 Окт 2019 в 00:47

Используйте эффективную конечную переменную счетчика, внешнюю по отношению к потоку.

Поскольку вставка идет по порядку, вам не обязательно, чтобы последняя карта была TreeMap; это может быть более быстрый LinkedHashMap, чей порядок итерации такой же, как и при вставке.

AtomicInteger counter = new AtomicInteger();
Map<Integer, MyClass> map = sortedSet.stream()
  .collect(Collectors.toMap(
    x -> counter.getAndIncrement(),
    x -> x,
    (a, b) -> a,
    LinkedHashMap::new));

Если вам отчаянно нужен TreeMap, замените LinkedHashMap на TreeMap в приведенном выше коде.

0
Bohemian 26 Окт 2019 в 00:53
Не предпочел бы использовать AtomicInteger только для этой цели.
 – 
Novice User
26 Окт 2019 в 00:42
Почему? В чем проблема с использованием такого счетчика? Также обратите внимание на изменения в моем ответе.
 – 
Bohemian♦
26 Окт 2019 в 00:53
1
Это зависит от порядка обработки, идентичного порядку встречи. Это предположение не выполняется для параллельных потоков, но спецификация намеренно не дает никаких гарантий для порядка обработки последовательных потоков. Таким образом, вы платите цену за поточно-безопасные конструкции (AtomicInteger не предоставляется бесплатно) за решение, которое не работает параллельно и противодействует намерениям API, но при этом является более сложным, чем простой цикл
 – 
Holger
28 Окт 2019 в 17:34