2016-04-07 2 views
3

У меня есть метод (из которого я не могу изменить параметры, иначе это могло быть упрощено с помощью HashMaps ... подробнее об этом позже), который передает элемент в качестве параметра. Теперь у меня есть список экземпляров из этого другого класса, из которых один из его атрибутов имеет один и тот же тип этого элемента, и я хочу найти экземпляры в списке, которые соответствуют этому элементу (из которых должен быть только один). Это то, что я сделал, чтобы найти это:Как получить доступ к первому ненулевому члену списка в Java?

List<Instance> instances = ... 

public static void checkItems(Item i) { 

    List<Instance> n = new ArrayList<>(); 
    instances.forEach(p -> n.add(p.i == i ? p : null)); 

    Instance currentInstance = n.get(0); 
    //Instance currentInstance = instances.stream().filter(p -> p.i == i).collect(Collectors.toList()).get(0); 

} 

Вы, вероятно, заметили две вещи прямо:

  1. я использовал условный оператор, который добавляет пустое значение в списке, когда условие ISN» т прошло
  2. Мой комментировал код, который был еще одна попытка решить эту проблему

Таким образом, в первом случае, я ставлю пустой, потому что она требует от вас, чтобы положить что-то, и нулевое значение probabl y работать проще, поэтому возникает вопрос: как мне получить доступ к первому ненулевому значению в списке (не прибегая к повторению по всему списку, чтобы найти его ...)?

Вы можете заметить, что я просто назначил первое значение списка n.get(0) на currentInstance, потому что я знаю, что только одно значение пройдет тест. Однако из-за некоторого другого кода, который я применяю к currentInstance, это значение не может быть нулевым.

Просто примечание по второму пункту: способ, которым я пытался его решить с потоками, работает точно так, как планировалось, за исключением того, что список восстановленных экземпляров по какой-то причине не является прямой копией исходных экземпляров. Это привело к тому, что значения некоторых атрибутов были сброшены до значений по умолчанию, поэтому этот метод бесполезен.

EDIT: Я просто хотел упомянуть, что метод streams не работал из-за какой-то глупой ошибки, которую я сделал в другом классе, ничего не случилось с кодом, поэтому я буду использовать этот бит для решения моей проблемы : D

+1

'instances.forEach (р -> если (р == я) n.add (р)),' –

+1

У меня трудно понять, что ваш вопрос, и что этот метод должен делать. Он ничего не возвращает и не изменяет никакого состояния, поэтому ничего не делает. –

+0

@JBNizet Это потому, что это всего лишь фрагмент этого рода большой вещи, которую я пишу, я не хотел добавленной путаницы, написав весь другой бессмысленный код. –

ответ

4

Если вы знаете, что только один p проходит тест, я не знаю, в чем смысл создания списка с нагрузкой null значениями плюс p есть.

Ваша проблема, похоже, связана с желанием использовать forEach. На мой взгляд, вы должны almost always use a for loop in preference to forEach. С простым циклом for вы можете просто использовать break, когда элемент найден.

Подробно:

Instance p = null; 
for (Instance q : instances) { 
    if (q.i == i) { 
     p = q; 
     break; 
    } 
} 
if (p == null) 
    throw new IllegalStateException(); // It wasn't there. 
// Do something with p. 
+0

Да, 'forEach()' - это когда вы хотите что-то делать с каждым элементом. Это не замена для петли. – Radiodef

+0

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

+1

@Radiodef Я никогда не использую его. Мне очень нравится ответ, на который я связан, хотя это скорее напыщенная речь. –

2

Вы можете сделать это, как

instances.forEach(p -> { 
    if (p.i == i) n.add(p); 
}); 
+0

Хорошо, я не знал, что вы можете использовать такой синтаксис , благодаря! –

+0

Eclipse говорит мне, что правильный синтаксис - это ... ... (p -> {if (p.i == i) n.add (p);}); 'с добавленным'; 'перед'} '. Надеюсь, это правильно ... –

+0

yea sry, я обновил свой ответ – Dimi

3

Вы могли бы сделать это следующим образом:

Instance currentInstance = instances.stream() 
    .filter(p -> p.i == i) 
    .findFirst() 
    .get(); // you can use get if you are sure there's one instance 

p -> p.i == i предикат кажется подозрительным. Почему бы не использовать equals() вместо этого?

3

Как описано выше, это будет обычно решается с потоками следующим образом:

Optional<Instance> first = 
    instances.stream().filter(p -> p.i == i).findFirst(); 

(из которых должен быть только один)

которого определенно является только один, или из них может быть более одного. (И если есть более одного, то что? Это ошибка?) Похоже, что вы должны иметь Set<Instance>, а не List<Instance>. Просто наблюдение.

+0

Это немного сложнее, чем в реальной программе, я просто хотел сохранить немного контекста, поэтому я упомянул об этих ограничениях. В целом меня просто интересовало, как решить эту конкретную проблему. –

Смежные вопросы