как манипулировать списком в Java - PullRequest
2 голосов
/ 21 июня 2009

Редактировать: Мой список отсортирован по БД У меня есть ArrayList, который имеет объекты класса People. У людей есть два свойства: ssn и terminationReason. Итак, мой список выглядит так

ArrayList: 
ssn            TerminatinoReason
123456789      Reason1
123456789      Reason2
123456789      Reason3
568956899      Reason2
000000001      Reason3
000000001      Reason2

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

так что приведенный выше список станет

New ArrayList: 
ssn            TerminatinoReason
123456789      Reason1, Reason2, Reason3
568956899      Reason2
000000001      Reason3, Reason2

У меня что-то происходит, когда я перебираю исходный список и сопоставляю ssn, но, похоже, это не работает.

Может кто-нибудь помочь?

Код, который я использовал, был:

    String ssn = "";
    Iterator it = results.iterator();
    ArrayList newList = new ArrayList();
    People ob;
    while (it.hasNext())
    {
       ob = (People) it.next();
       if (ssn.equalsIgnoreCase(""))
       {
           newList.add(ob);
           ssn = ob.getSSN();
       }
       else if (ssn.equalsIgnoreCase(ob.getSSN()))
       {
           //should I get last object from new list and append this termination reason?
            ob.getTerminationReason()
       }
    }

Ответы [ 5 ]

5 голосов
/ 21 июня 2009

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

Google Collections имеет реализацию Multimap.

Это может означать, что поля ssn и terminationReason объекта Person, возможно, должны быть удалены как ключ и значение соответственно. (И эти поля будут считаться String.)

По сути, его можно использовать следующим образом:

Multimap<String, String> m = HashMultimap.create();

// In reality, the following would probably be iterating over the
// Person objects returned from the database, and calling the
// getSSN and getTerminationReasons methods.

m.put("0000001", "Reason1");
m.put("0000001", "Reason2");
m.put("0000001", "Reason3");
m.put("0000002", "Reason1");
m.put("0000002", "Reason2");
m.put("0000002", "Reason3");

for (String ssn : m.keySet())
{
    // For each SSN, the termination reasons can be retrieved.
    Collection<String> termReasonsList = m.get(ssn);

    // Do something with the list of reasons.
}

При необходимости можно создать разделенный запятыми список Collection:

StringBuilder sb = new StringBuilder();

for (String reason : termReasonsList)
{
    sb.append(reason);
    sb.append(", ");
}

sb.delete(sb.length() - 2, sb.length());
String commaSepList = sb.toString();

Это может быть снова установлено в поле terminationReason.

Альтернативой, как упоминал Джоник в комментариях, является использование метода StringUtils.join из Apache Commons Lang можно использовать для создания списка через запятую. *

Следует также отметить, что Multimap не определяет, должна ли реализация разрешать или не разрешать дублирование пар ключ / значение, поэтому следует посмотреть, какой тип Multimap использовать .

В этом примере HashMultimap является хорошим выбором, поскольку он не допускает дублирование пар ключ / значение. Это автоматически устранит любые повторяющиеся причины, приведенные для одного конкретного человека.

3 голосов
/ 21 июня 2009

Вам может понадобиться хэш. Возможно, HashMap можно использовать.

Переопределите equals () и hashCode () внутри вашего класса людей.

Сделать hashCode вернуть SSN людей (человек). Таким образом, вы будете иметь все объекты People с одним и тем же SSN в одном «ведре».

Помните, что классы реализации интерфейса Map используют пары ключ / значение для хранения ваших объектов, поэтому у вас будет что-то вроде myHashMap.add ("ssn", peopleobject);

3 голосов
/ 21 июня 2009
List<People> newlst = new ArrayList<People>();
People last = null;
for (People p : listFromDB) {
   if (last == null || !last.ssn.equals(p.ssn)) {
      last = new People();
      last.ssn = p.ssn;
      last.terminationReason = "";
      newlst.add(last);  
   }
   if (last.terminationReason.length() > 0) {
      last.terminationReason += ", ";
   }
   last.terminationReason += p.terminationReason;
}

И вы получите агрегированный список в новом.

Обновление: Если вы используете MySQL, вы можете использовать функцию GROUP_CONCAT для извлечения данных в требуемом формате. Я не знаю, имеют ли другие двигатели БД похожую функцию или нет.

Обновление 2: Удалена ненужная сортировка.

1 голос
/ 21 июня 2009

Две возможные проблемы:

  • Это не будет работать, если ваш список не отсортирован
  • Вы ничего не делаете с ob.getTerminationReason () . Я думаю, что вы хотите добавить его к предыдущему объекту.
0 голосов
/ 21 июня 2009

РЕДАКТИРОВАТЬ: Теперь я вижу, что вы отредактировали свой вопрос.

Поскольку ваш список отсортирован, (по ssn я предполагаю)

Integer currentSSN = null;
List<People> peoplelist = getSortedList();//gets sorted list from DB.
/*Uses foreach construct instead of iterators*/

for (People person:peopleList){

 if (currentSSN != null && people.getSSN().equals(currentSSN)){
 //same person
 system.out.print(person.getReason()+" ");//writes termination reason

 } 
 else{//person has changed. New row.
   currentSSN = person.getSSN();
   system.out.println(" ");//new row.
   system.out.print(person.getSSN()+ " ");//writes row header.
 }

}

Если вы не хотите отображать содержимое вашего списка, вы можете использовать его для создания MAP, а затем использовать его, как показано ниже.

Если ваш список не отсортирован

Возможно, вам следует попробовать другой подход, используя Карту. Здесь ssn будет ключом карты, а значения могут быть списком людей

Map<Integer,List<People>> mymap = getMap();//loads a Map from input data.

for(Integer ssn:mymap.keyset()){
 dorow(ssn,mymap.get(ssn));
}

public void dorow(Integer ssn, List<People> reasons){

system.out.print(ssn+" ");
for (People people:reasons){
system.out.print(people.getTerminationReason()+" ");
}

system.out.println("-----");//row separator.

И последнее, но не менее важное: вы должны переопределить методы hashCode () и equals () в классе People.

например

public void int hashcode(){

  return 3*this.reason.hascode();

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...