Обновление объекта в Наборе

Стандартная консольная Java просто не может этого сделать. Все вводимые символы буферизуются до тех пор, пока вы не нажмете Enter, и в этот момент все они доступны на System.in.

Итак, если вы зациклите свой код «нажмите любую клавишу», скажем, 5 раз, и я наберу предложение «привет!», Ваш код все еще застревает на первом, ожидая нажатия клавиши. Если я затем нажму Enter, все 5 циклов завершатся немедленно, и если вы вызовете waitForKey позже, он мгновенно вернется еще 2–3 раза (один раз для восклицательного знака и один раз для новой строки ... дважды, если в Windows потому что их переводы строки 2 символа).

TL; DR: Вы не можете использовать System.in.read() для этого. На всех.

Одно из решений состоит в том, чтобы попросить пользователя не нажимать клавишу «любая», а нажать клавишу «ввод», а затем использовать, например, вызов сканера next() после установки разделителя на новую строку или написать код, который продолжает вызывать System.in.read(), пока не вернет '\ n':

private void pressEnterToContinue() {
    while (true) {
        int c;
        try {
            c = System.in.read();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        if (c == -1 || c == '\n') return;
    }
}
16
задан Yuval 7 October 2008 в 08:39
поделиться

7 ответов

Вы действительно хотите использовать Map<Integer,A>, не Set<A>.

Тогда отображают идентификатор (даже при том, что он также хранится в A!) к объекту. Так новое хранение является этим:

A a = ...;
Map<Integer,A> map = new HashMap<Integer,A>();
map.put( a.id, a );

Ваш полный алгоритм обновления:

public static void update( Map<Integer,A> map, A obj ) {
  A existing = map.get( obj.id );
  if ( existing == null )
     map.put( obj.id, obj );
  else
     existing.b = obj.b;
}

Однако это могло бы быть еще более просто. я предполагаю, что у Вас есть больше полей, чем это в A это, что Вы дали. , Если дело обстоит не так , просто с помощью Map<Integer,B> на самом деле, что Вы хотите, тогда это не выходит из строя ни к чему:

Map<Integer,B> map = new HashMap<Integer,B>();
// The insert-or-update is just this:
map.put( id, b );
11
ответ дан 30 November 2019 в 16:30
поделиться

Я не думаю, что можно сделать его немного легче, чем использование удаляет/добавляет при использовании Набора.

    set.remove(a);
    set.add(a);

, Если соответствие A было найдено, оно будет удалено, и затем Вы добавляете новый, Вам даже не нужно if (set.contains(A)) условное выражение.

, Если у Вас есть объект с идентификатором и обновленным полем и , Вы действительно не заботитесь ни о каких других аспектах того объекта, просто выводите его и заменяете его.

, Если необходимо сделать что-либо еще к, который соответствует тому идентификатору тогда, необходимо будет выполнить итерации через Набор, чтобы найти его или использовать различный Контейнер (как Карта как предложенный Jason).

6
ответ дан 30 November 2019 в 16:30
поделиться

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

Вместо этого я настоятельно рекомендую передать идентификатор на пути конструктор, и если необходимо изменить его, создайте новый экземпляр A. Это вынудит пользователей Вашего объекта (включая себя) правильно взаимодействовать с классами набора (и многие другие), которые полагаются на неизменное поведение в, равняется и хэш-код.

4
ответ дан 30 November 2019 в 16:30
поделиться

Что относительно Карты <A,A> я знаю, что это избыточно, но я полагаю, что это получит Вас поведение, которое Вы хотели бы. Действительно я хотел бы видеть, Набор иметь получать (Возразите o), метод на нем.

1
ответ дан 30 November 2019 в 16:30
поделиться

Вы могли бы хотеть генерировать декоратора под названием ASet и использовать внутреннюю Карту в качестве отступающей структуры данных

class ASet {
 private Map<Integer, A> map;
 public ASet() {
  map = new HashMap<Integer, A>();
 }

 public A updateOrAdd(Integer id, int delta) {
   A a = map.get(a);
   if(a == null) {
    a = new A(id);
    map.put(id,a);
   }
   a.setX(a.getX() + delta);
 }
}

, можно также смотреть на API Находки. В то время как это лучше для производительности, и для учета этого Вы работаете с примитивными переменными, это представляет эту функцию очень приятно (например, map.adjustOrPutValue (ключ, initialValue, deltaValue).

0
ответ дан 30 November 2019 в 16:30
поделиться

Это - немного внешнего объема, но Вы забыли повторно реализовывать хэш-код (). То, когда Вы переопределяете, равняется, переопределите хэш-код (), даже в примере.

, Например; содержит (), очень, вероятно, пойдет не так, как надо, когда у Вас есть реализация HashSet Набора, поскольку HashSet использует хэш-код Объекта определить местоположение блока (число, которое не имеет никакого отношения к бизнес-логике), и только равняется () элементам в том блоке.

public class A {
  public int id;
  public B b;
  public int hashCode() {return id;} // simple and efficient enough for small Sets 
  public boolean equals(Object another) { 
    if (object == null || ! (object instanceOf A) ) {
      return false;
    }
    return this.id == ((A)another).id; 
   }
}
public class Logic {
  /**
   * Replace the element in data with the same id as element, or add element
   * to data when the id of element is not yet used by any A in data. 
   */
  public void update(Set<A> data, A element) {
    data.remove(element); // Safe even if the element is not in the Set
    data.add(element); 
  }
}

РЕДАКТИРОВАНИЕ Yuvalindicated правильно, что Set.add не перезаписывает существующий элемент, но только добавляет, не находится ли элемент еще в наборе (с реализован, равняется)

0
ответ дан 30 November 2019 в 16:30
поделиться

Так как Набор может только содержать один экземпляр объекта (как определено, равняется и методы хэш-кода), просто удалите его и затем добавьте его. Если уже был тот, что другой будет удален из Набора и заменен тем, Вы хотите.

у меня есть код, который делает что-то подобное - я кэширую объекты так, чтобы везде конкретный объект появился в наборе различных мест на gui, это всегда - тот же. В этом случае вместо того, чтобы использовать Набор я использую Карту, и затем я получаю обновление, я получаю его из Карты и обновляю его на месте вместо того, чтобы создать новый экземпляр.

17
ответ дан 30 November 2019 в 16:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: