#java #list #collections #arraylist #mixed
#java #Список #Коллекции #список массивов #смешанный
Вопрос:
Возможно ли хранить смесь типов объектов в ArrayList? Если да, то каким образом?
Это то, что я пробовал до сих пор:
List<Object> list = new ArrayList<Object>();
list.add(new String("Hello World"));
list.add(new Integer(1));
list.add(new Long(1l));
for (i = 0; i < list.size(); i ) {
if (list.get(i) instanceof String){
sqlPreparedStatement.setString((i 1), (String) list.get(i));
} else if (list.get(i) instanceof Integer) {
sqlPreparedStatement.setInt((i 1), (Integer) list.get(i));
} else if (list.get(i) instanceof Long) {
sqlPreparedStatement.setLong((i 1), (Long) list.get(i));
}
}
Но это создает исключение приведения.
Заранее спасибо за любой вклад!
Комментарии:
1. Определите «не работает».
2. Зачем параметризовать с помощью Object? Что вы получаете при этом?
3. @Jeremy: Это позволяет избежать раздражающего волнистого желтого подчеркивания в Eclipse!
4. Покажите трассировку стека вашего исключения, пожалуйста. Интересным моментом был бы номер строки ClassCastException (и отметьте этот номер в исходном коде). Исходный код выглядит нормально, за исключением некоторых оптимизаций, как в ответе от scientiaesthete , и лишнего
new String(...)
там.5. @Paulo прав. Правильный способ выяснить, что происходит не так, — это посмотреть на трассировку стека. Соответствует ли порядок вашего списка тому, что происходит в вашем PreparedStatement?
Ответ №1:
Это то, что у вас должно быть:
List<Object> list = new ArrayList<Object>();
list.add(new String("Hello World"));
list.add(new Integer(1));
list.add(new Long(1l));
for (Object obj: list) {
if (obj instanceof String){
sqlPreparedStatement.setString((String) obj);
} else if (obj instanceof Integer) {
sqlPreparedStatement.setInt((Integer) obj);
} else if (obj instanceof Long) {
sqlPreparedStatement.setLong((Long) obj);
}
}
Комментарии:
1. Кстати, в «новой строке()» нет необходимости.
2. @scientiaesthete : Помимо того, что List#get(int) вызывается в два раза чаще, чем в вашем, и использования итератора, нет никакой разницы между вашим фрагментом кода и OP. Я что-то здесь упускаю — в чем разница в отношении приведения?
3. @bguiz Сигнатуры setXXX() отличаются. У OP было
setXXX(int, XXXthing)
, у этого только чтоsetXXX(XXXthing)
. Мне кажется, один из них не соответствует API.4. @Atreys: да, этот «ответ» неверен, и на самом деле код операционной системы является лучшим из двух, поскольку он фактически компилируется и предоставляет циклу for параметр int, который может использоваться в вызовах метода подготовленной инструкции. Я должен задаться вопросом, как этот ответ получил 5 голосов «За»? Я проголосовал против.
5. На самом деле нет необходимости ни в одном из
new
с автоматической упаковкой.
Ответ №2:
Извините, что прерываю ваш парад, но для начала вам не следует использовать ArrayList из 3 (или любых) разных типов. Если информация связана, создайте класс, который содержит связанную информацию, и создайте ArrayList, который содержит только один тип: объекты этого класса.
Правка 1:
Например, скажем, класс для хранения данных следующим образом:
class SqlData {
private String textData;
private int intData;
private long longData;
public SqlData(String textData, int intData, long longData) {
this.textData = textData;
this.intData = intData;
this.longData = longData;
}
public String getTextData() {
return textData;
}
public int getIntData() {
return intData;
}
public long getLongData() {
return longData;
}
}
и используется примерно так:
List<SqlData> sqlDataList = new ArrayList<SqlData>();
sqlDataList.add(new SqlData("Hello World", 1, 11L));
for (int i = 0; i < sqlDataList.size(); i ) {
try {
sqlPreparedStatement.setString(i 1, sqlDataList.get(i).getTextData());
sqlPreparedStatement.setInt(i 1, sqlDataList.get(i).getIntData());
sqlPreparedStatement.setLong(i 1, sqlDataList.get(i).getLongData());
} catch (SQLException e) {
e.printStackTrace();
}
}
Комментарии:
1. Этот подход более описательный. Но я думаю, что нам здесь не нужны
sqlDataList
иfor
цикл.2. 1 @Hovercraft : Просто чтобы противодействовать «мести», которую вы, вероятно, получили; И я также согласен, что вы не должны смешивать объекты разных типов в любом списке в первую очередь; За возможным исключением типов, которые наследуются (подчиняется правилу «is-a»)
3. Даже если вы не должны смешивать объекты разных типов в списке, это не означает, что люди не могут и что не существует программного обеспечения, содержащего этот тип кода.
4. @Atreys: Это не вопрос «не могу», а скорее вопрос создания программного обеспечения, которое трудно отлаживать, поддерживать и расширять, когда кто-то следует таким плохим практикам, как эта.
5. Мне действительно нравится этот ответ, потому что он учит вас правильному способу выполнения действий! Так часто люди дают ответы просто для того, чтобы дать ответы, вместо того, чтобы смотреть на общую картину!
Ответ №3:
Почему вы делаете это так сложно? у PreparedStatement
есть setObject()
метод — просто используйте это:
List<Object> list = new ArrayList<Object>();
list.add(new String("Hello World"));
list.add(new Integer(1));
list.add(new Long(1l));
for (int i = 0; i < list.size(); i )
sqlPreparedStatement.setObject(i 1, list.get(i)); // NOTE: columns count from 1
ПРИМЕЧАНИЕ: java SQL API считает все от 1, а не от нуля, поэтому столбцы нумеруются 1 … size(), а не 0 … size ()-1