Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Поиск по Vector пользовательского типа


Автор: triclosan 10.10.2006, 11:21
Храню данные в контейнере типа Vector. Каждый элемент - объект класса:
Код

Vector<SubstanceData> vsub = new Vector<SubstanceData>();
...
public class SubstanceData
{
    int cd_id;
    String idnumber;
    double available, amount;
}


Не пойму, как искать элемент, например, по заданному значению idnumber? Можно ли здесь использовать метод indexOf?


Автор: batigoal 10.10.2006, 11:35
Цитата(triclosan @  10.10.2006,  12:21 Найти цитируемый пост)
Не пойму, как искать элемент, например, по заданному значению idnumber? 

Исключительно перебором.

Добавлено @ 11:36 
В общем случае, разумеется.

Автор: LSD 10.10.2006, 11:37
В коллекциях для поиска элементов используется метод equals(). Если надо делать сложный поиск объекта, используй TreeSet и свой Comparator.

И почитай http://vingrad.ru/JAVA-ART-003066 статью, и статьи по ссылкам.

Автор: triclosan 10.10.2006, 11:55
спасибо за ответы, буду пробовать. 

Автор: NotGonnaGetUs 10.10.2006, 12:57
Цитата(LSD @  10.10.2006,  11:37 Найти цитируемый пост)
И почитай эту статью,


От туда: 
"Коллекции часто рассматривают объекты как одинаковые, если у них одинаковый хэшкод."

Лучше это исправить, если есть возможность.


Автор: triclosan 10.10.2006, 17:56
Элементов не так уж много поэтому решил использовать перебор в лоб. 

Метод удаляет выбранный элемент вектора поиск производится по параметру idnumber, но при выполнении выдает ConcurrentModificationException.
Код

int ii=0;
SubstanceData temp=new SubstanceData();
        
for(Iterator <SubstanceData> i = vsub.iterator(); i.hasNext();) 
{
            
    temp=i.next();
    if(temp.idnumber.equals(value))
    vsub.removeElementAt(ii);
    ii++;
}


Это метод класса, используемого как JavaBean в JSP, вот такие ошибки сообщает:


type Exception report

message

description The server encountered an internal error () that prevented it from fulfilling this request.

exception

org.apache.jasper.JasperException
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:373)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:295)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:245)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:802)

root cause

java.util.ConcurrentModificationException
    java.util.AbstractList$Itr.checkForComodification(Unknown Source)
    java.util.AbstractList$Itr.next(Unknown Source)
    net.enamine.shop.UserData.deleteSubstance(UserData.java:84)
    org.apache.jsp.my.vieworder_jsp._jspService(org.apache.jsp.my.vieworder_jsp:115)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:99)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:325)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:295)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:245)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:802)

note The full stack trace of the root cause is available in the Apache Tomcat/5.5.7 logs.


В документации Sun это объясняется некими fail-fast итераторами только не пойму как с ними бороться.

Автор: batigoal 10.10.2006, 19:13
Видимо, дело в том, что ты одновременно читаешь вектор (через итератор), и пытаешься его внутри этого итератора перезаписать.

Автор: triclosan 10.10.2006, 20:24
Да, перенос удаления после цикла с итератором спасло отца русской демократии smile 

Автор: LSD 10.10.2006, 21:24
У Iterator-а есть метод remove(), для удаления текущего элемента. Вот им и надо удалять, тогда ошибок не будет.

Автор: triclosan 10.10.2006, 21:32
Цитата(LSD @  10.10.2006,  21:24 Найти цитируемый пост)
У Iterator-а есть метод remove(), для удаления текущего элемента. Вот им и надо удалять, тогда ошибок не будет. 

Здорово, а то я лучше не придумал, чем дополнительную переменную ввести, матчасть хромает...

Автор: triclosan 11.10.2006, 13:15
А как вызывать методы класса для объектов в коллекции?

В С++ можно по индексу, а в JAVA как?

Автор: batigoal 11.10.2006, 13:19
Цитата(triclosan @  11.10.2006,  14:15 Найти цитируемый пост)
А как вызывать методы класса для объектов в коллекции?

Код

for(Iterator <SubstanceData> i = vsub.iterator(); i.hasNext();) 
{
            
    temp=i.next();
    temp.someMethod();
}


Если коллекция поддерживает доступ по индексу, то можно и
Код

collection.get(index).someMethod();

Автор: Stampede 11.10.2006, 18:14
Цитата(batigoal @  11.10.2006,  04:19 Найти цитируемый пост)
Код

for(Iterator <SubstanceData> i = vsub.iterator(); i.hasNext();) 
{
            
    temp=i.next();
    temp.someMethod();
}



Не совсем верно. В таком виде, как тут написано, компилятор выдаст ошибку: необъявленная переменная temp. Кроме того, коль скоро я вижу тут generics, то речь идет об 1.5, а в нем для итерирования предусмотрен гораздо более компактный синтаксис:

Код

    List<SubstanceData> list = someService.getSubstanceDataList();
    for(SubstanceData temp : list)  {
                  temp.someMethod();
    }


И фсе! Весь итератор - в одну строку.

Автор: batigoal 11.10.2006, 21:22
Цитата(Stampede @  11.10.2006,  19:14 Найти цитируемый пост)
Не совсем верно. В таком виде, как тут написано, компилятор выдаст ошибку: необъявленная переменная temp. Кроме того, коль скоро я вижу тут generics, то речь идет об 1.5, а в нем для итерирования предусмотрен гораздо более компактный синтаксис:

Это я кусок кода из примера товарища triclosan выдрал.

Автор: Stampede 11.10.2006, 22:18
Цитата(batigoal @  11.10.2006,  12:22 Найти цитируемый пост)
Это я кусок кода из примера товарища triclosan выдрал.


А, вижу. Там переменная temp объявлена вне цикла. 

triclosan, по этому поводу у Блоха в "Effective Java" есть отдельный совет:

Цитата

Item 29: Minimize the scope of local variables

This item is similar in nature to Item 12, “Minimize the accessibility of classes and members.” By minimizing the scope of local variables, you increase the readability and maintainability of your code and reduce the likelihood of error.
...

Loops present a special opportunity to minimize the scope of variables. The for loop allows you to declare loop variables, limiting their scope to the exact region where they're needed. (This region consists of the body of the loop as well as the initialization, test, and update preceding the body.)


То есть по-хорошему этот кусок следовало бы переписать так (с учетом замечания LSD об удалении из итератора):

Код

for (Iterator<SubstanceData> i = vsub.iterator(); i.hasNext();) 
{
    SubstanceData temp = i.next();
    if (temp.idnumber.equals(value)) {
        i.remove();
    }
}


Коротко, наглядно и безопасно smile

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

Автор: triclosan 12.10.2006, 00:34
Цитата(Stampede @  11.10.2006,  22:18 Найти цитируемый пост)
по этому поводу у Блоха в "Effective Java" есть отдельный совет:


Такую привычку, программируя на С приобрел. Разве в случае объявления внутри цикла переменная будет видна только там smile ?

Автор: batigoal 12.10.2006, 08:11
Цитата(triclosan @  12.10.2006,  01:34 Найти цитируемый пост)
Разве в случае объявления внутри цикла переменная будет видна только там smile ? 

Разумеется. Локальная переменная существует только внутри блока кода.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)