Подтвердить что ты не робот

Хороший способ получить * любое значение из набора Java?

Учитывая простой Set<T>, что хороший способ (быстрая, несколько строк кода) получить любое значение из Set?

С a List легко:

List<T> things = ...;
return things.get(0);

Но, с Set, метода .get(...) нет, потому что Set не упорядочены.

4b9b3361

Ответ 1

A Set<T> является Iterable<T>, поэтому выполняется итерация первого элемента:

Set<T> things = ...;
return things.iterator().next();

Guava имеет метод для этого, хотя приведенный выше фрагмент скорее всего, лучше.

Ответ 2

Получение любого элемента из набора или коллекции может показаться необычным спросом - если не произвольным или эклектичным - но это довольно часто, когда, например, нужно вычислять статистику для объектов Keys или Values ​​в Карта и должны инициализировать минимальные/максимальные значения. Любой элемент из Set/Collection (возвращаемый Map.keySet() или Map.values ​​()) будет использоваться для этой инициализации до обновления значений min/max над каждым элементом.

Итак, какие у вас есть варианты, когда сталкиваетесь с этой проблемой, и в то же время пытаетесь сохранить память и время выполнения малым и код понятным?

Часто вы получаете обычное: "конвертируйте Set в ArrayList и получите первый элемент". Большой! Еще один массив из миллионов элементов и дополнительных циклов обработки для извлечения объектов из Set, выделения массива и заполнения его:

HashMap<K,V> map;
List<K> list = new ArrayList<V>(map.keySet()); // min/max of keys
min = max = list.get(0).some_property(); // initialisation step
for(i=list.size();i-->1;){
 if( min > list.get(i).some_property() ){ ... }
 ...
}

Или можно использовать looping с Iterator, используя флаг, чтобы обозначить, что min/max необходимо инициализировать, и условный оператор, чтобы проверить, установлен ли этот флаг для всех итераций в цикле. Это подразумевает много условной проверки.

boolean flag = true;
Iterator it = map.keySet().iterator();
while( it.hasNext() ){
  if( flag ){
    // initialisation step
    min = max = it.next().some_property();
    flag = false;
  } else {
    if( min > list.get(i).some_property() ){ min = list.get(i).some_property() }
  ...
  }
}

Или выполните инициализацию вне цикла:

HashMap<K,V> map;
Iterator it = map.keySet().iterator();
K akey;
if( it.hasNext() ){
  // initialisation step:
  akey = it.next();
  min = max = akey.value();
  do {
    if( min > list.get(i).some_property() ){ min = akey.some_property() }
  } while( it.hasNext() && ((akey=it.next())!=null) );
}

Но действительно ли стоит этот маневр от имени программиста (и создания Итератора от имени JVM) всякий раз, когда требуется мин/макс?

Предложение от javally-correct ol 'sport вполне может быть: "оберните свою карту в классе, который отслеживает минимальные и максимальные значения при установке или удалении!".

Есть еще одна ситуация, которая, по моему опыту, вызывает необходимость только для любого элемента Карты. Это когда карта содержит объекты, которые имеют общее свойство - все равно для всех из них на этой карте, - и вам нужно прочитать это свойство. Например, предположим, что имеется карта хранения бункеров той же гистограммы, которые имеют одинаковое количество измерений. Для такой Карты вам может понадобиться знать количество измерений только любого Histobin на Карте, чтобы, например, создать другой Histobin с теми же размерами. Нужно ли снова настраивать итератор и удалять его после вызова next() только один раз? Я пропущу правильное предложение человека в этой ситуации.

И если все проблемы с получением какого-либо элемента приводят к незначительным циклам памяти и процессора, то как насчет всего кода, который нужно написать, чтобы получить труднодоступный элемент.

Нам нужен любой элемент. Дайте это нам!