Стандартная консольная 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;
}
}
Вы действительно хотите использовать 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 );
Я не думаю, что можно сделать его немного легче, чем использование удаляет/добавляет при использовании Набора.
set.remove(a);
set.add(a);
, Если соответствие A было найдено, оно будет удалено, и затем Вы добавляете новый, Вам даже не нужно if (set.contains(A))
условное выражение.
, Если у Вас есть объект с идентификатором и обновленным полем и , Вы действительно не заботитесь ни о каких других аспектах того объекта, просто выводите его и заменяете его.
, Если необходимо сделать что-либо еще к, который соответствует тому идентификатору тогда, необходимо будет выполнить итерации через Набор, чтобы найти его или использовать различный Контейнер (как Карта как предложенный Jason).
Никто еще не упомянул это, но основывающий хэш-код или равняется на изменяемом свойстве, один из тех действительно, действительно большие вещи, которые Вы не должны делать. Не слоняйтесь без дела с объектными идентификационными данными после отъезда конструктора - выполнение так сильно увеличивает возможности наличия действительно трудных к фигуре ошибок в будущем. Даже если Вы не становитесь пораженными ошибками, бухгалтерская работа, чтобы удостовериться, что Вы всегда правильно обновление, которому любой и все структуры данных, который полагается, равняются и хэш-код, являющийся последовательным, будет далеко перевешивать любые воспринятые преимущества способности просто изменить идентификатор объекта, когда Вы работаете.
Вместо этого я настоятельно рекомендую передать идентификатор на пути конструктор, и если необходимо изменить его, создайте новый экземпляр A. Это вынудит пользователей Вашего объекта (включая себя) правильно взаимодействовать с классами набора (и многие другие), которые полагаются на неизменное поведение в, равняется и хэш-код.
Что относительно Карты <A,A
> я знаю, что это избыточно, но я полагаю, что это получит Вас поведение, которое Вы хотели бы. Действительно я хотел бы видеть, Набор иметь получать (Возразите o), метод на нем.
Вы могли бы хотеть генерировать декоратора под названием 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).
Это - немного внешнего объема, но Вы забыли повторно реализовывать хэш-код (). То, когда Вы переопределяете, равняется, переопределите хэш-код (), даже в примере.
, Например; содержит (), очень, вероятно, пойдет не так, как надо, когда у Вас есть реализация 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 не перезаписывает существующий элемент, но только добавляет, не находится ли элемент еще в наборе (с реализован, равняется)
Так как Набор может только содержать один экземпляр объекта (как определено, равняется и методы хэш-кода), просто удалите его и затем добавьте его. Если уже был тот, что другой будет удален из Набора и заменен тем, Вы хотите.
у меня есть код, который делает что-то подобное - я кэширую объекты так, чтобы везде конкретный объект появился в наборе различных мест на gui, это всегда - тот же. В этом случае вместо того, чтобы использовать Набор я использую Карту, и затем я получаю обновление, я получаю его из Карты и обновляю его на месте вместо того, чтобы создать новый экземпляр.