Сравните новые целочисленные объекты в вопросе ArrayList

Я храню объекты Integer, представляющие индекс объектов, которые я хочу отслеживать. Позже в моем коде я хочу проверить, соответствует ли индекс конкретного объекта одному из тех целых чисел, которые я сохранил ранее. Я делаю это, создавая ArrayList и создавая новый Integer из индекса цикла for:

ArrayList<Integer> courseselectItems = new ArrayList();

//Find the course elements that are within a courseselect element and add their indicies to the ArrayList
for(int i=0; i<numberElementsInNodeList; i++) {
    if (nodeList.item(i).getParentNode().getNodeName().equals("courseselect")) {
        courseselectItems.add(new Integer(i));
    }
}

Затем я хочу проверить позже, содержит ли ArrayList определенный индекс:

//Cycle through the namedNodeMap array to find each of the course codes
for(int i=0; i<numberElementsInNodeList; i++) {
    if(!courseselectItems.contains(new Integer(i))) {
        //Do Stuff
    }
}

Мой вопрос: когда я создам новое целое число, используя new Integer(i), смогу ли я сравнивать целые числа, используя ArrayList.contains()? То есть, когда я создаю новый объект, используя new Integer(i), будет ли он таким же, как ранее созданный объект Integer, если значение int, используемое для их создания, одинаково?

Надеюсь, я не сделал это слишком неясным. Спасибо за помощь!


person ericso    schedule 13.04.2010    source источник
comment
Кстати, вот что стоит знать о целых числах и строках: devx.com/tips/Tip/42276   -  person James P.    schedule 14.04.2010


Ответы (7)


Да, вы можете использовать List.contains(), поскольку он использует equals(), а Integer поддерживает это по сравнению с другими Integer.

Кроме того, из-за автобокса вы можете просто написать:

List<Integer> list = new ArrayList<Integer>();
...
if (list.contains(37)) { // auto-boxed to Integer
  ...
}

Стоит отметить, что:

List list = new ArrayList();
list.add(new Integer(37));
if (list.contains(new Long(37)) {
  ...
}

будет всегда возвращать false, потому что Integer не является Long. В какой-то момент это сбивает с толку большинство людей.

Наконец, попробуйте создать свои переменные, которые являются коллекциями Java типа интерфейса, а не конкретного типа, поэтому:

List<Integer> courseselectItems = new ArrayList();

нет

ArrayList<Integer> courseselectItems = new ArrayList();
person cletus    schedule 13.04.2010
comment
Спасибо! Есть ли какая-то особая причина, по которой я хочу, чтобы мои переменные имели тип интерфейса, а не конкретный тип? - person ericso; 14.04.2010
comment
@thechiman конкретный тип - это деталь реализации. В общем параметры, локальные переменные и члены класса должны быть интерфейсом, чтобы вы не были привязаны к конкретной реализации. Это позволяет вам, например, позже подключить пользовательскую реализацию List и т. д. - person cletus; 14.04.2010
comment
Это не так важно, если List полностью приватен для класса и больше нигде не виден. Но если вы каким-то образом выставляете его (например, класс, содержащий список, имеет метод для возврата списка), то вы обязательно должны вернуть его как List, а не как ArrayList. Например, позже вы можете решить, что LinkedList является более подходящей реализацией. - person Iain Samuel McLean Elder; 14.04.2010

Мой вопрос: когда я создаю новое целое число с помощью нового целого числа (i), смогу ли я сравнивать целые числа с помощью ArrayList.contains ()? То есть, когда я создаю новый объект, используя new Integer(i), будет ли он таким же, как ранее созданный объект Integer, если значение int, используемое для их создания, одинаково?

Краткий ответ: да.

Длинный ответ...

То есть, когда я создаю новый объект с помощью new Integer(i), будет ли он таким же, как ранее созданный объект Integer, если значение int, используемое для их создания, одинаково?

Я предполагаю, что вы имели в виду "... будет ли это тот же экземпляр, что и..."? Ответ на этот вопрос нет — вызов new всегда будет создавать отдельный экземпляр, отдельный от предыдущего экземпляра, даже если параметры конструктора идентичны.

Однако, несмотря на наличие отдельных идентификаторов, эти два объекта будут иметь эквивалентное значение, т. е. вызов .equals() между ними вернет true.

Collection.contains()

Оказывается, наличие отдельных экземпляров эквивалентного значения (.equals() возвращает true) — это нормально. Метод .contains() находится в интерфейсе Collection. Описание Javadoc для .contains() гласит:

http://java.sun.com/javase/6/docs/api/java/util/Collection.html#contains(java.lang.Object)

логическое значение содержит (объект o)

Возвращает true, если эта коллекция содержит указанный элемент. Более формально возвращает true тогда и только тогда, когда эта коллекция содержит хотя бы один элемент e, такой что (o==null ? e==null : o.equals(e)).

Таким образом, он будет делать то, что вы хотите.

Структура данных

Вы также должны подумать, правильная ли у вас структура данных.

Список касается исключительно сдерживания? порядок важен? Вас волнуют дубликаты? Поскольку список — это порядок, использование списка может означать, что ваш код заботится об упорядочении. Или что вам нужно поддерживать дубликаты в структуре данных.

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

person Bert F    schedule 14.04.2010

Короткий ответ: да, вы должны иметь возможность сделать ArrayList.contains(new Integer(14)), например, чтобы увидеть, есть ли 14 в списке. Причина в том, что Integer переопределяет метод equals, чтобы корректно сравнивать себя с другими экземплярами с таким же значением.

person Sean    schedule 13.04.2010

Да, так как List.contains() используется метод equals() сравниваемого объекта. И Integer.equals() действительно сравнивает целочисленное значение.

person DJ.    schedule 13.04.2010

Как упомянули Клетус и ДиДжей, ваш подход сработает.

Я не знаю контекст вашего кода, но если вас не интересуют конкретные индексы, рассмотрите также следующий стиль:

List<Node> courseSelectNodes = new ArrayList<Node>();

//Find the course elements that are within a courseselect element 
//and add them to the ArrayList
for(Node node : numberElementsInNodeList) {
    if (node.getParentNode().getNodeName().equals("courseselect")) {
        courseSelectNodes.add(node);
    }
}

// Do stuff with courseSelectNodes
for(Node node : courseSelectNodes) {
    //Do Stuff
}
person Binil Thomas    schedule 13.04.2010
comment
В итоге я изменил свой код, чтобы сделать что-то похожее на это. Спасибо! - person ericso; 14.04.2010

Я привожу свой ответ в виде (проходного) теста в качестве примера того, как вы можете исследовать это самостоятельно. Не для того, чтобы отговорить вас от использования SO — это здорово — просто попытаться продвигать тесты характеристик.

import java.util.ArrayList;
import junit.framework.TestCase;

public class ContainsTest extends TestCase {
    public void testContains() throws Exception {
        ArrayList<Integer> list = new ArrayList<Integer>();
        assertFalse(list.contains(new Integer(17)));
        list.add(new Integer(17));
        assertTrue(list.contains(new Integer(17)));
    }
}
person Carl Manaster    schedule 13.04.2010
comment
Да, теперь, когда я думаю об этом, я мог бы легко проверить это на себе. Хех, я чувствую себя глупо. Спасибо. :) - person ericso; 14.04.2010

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

Кроме того, из-за упаковки создание класса Integer вручную является излишним.

person nick    schedule 13.04.2010