2009-06-21 2 views
2

Редактировать: Мой список отсортирован относительно базы данных У меня есть ArrayList, где есть объекты класса People. У людей есть два свойства: ssn и termReason. Так что мой список выглядит следующим образомКак манипулировать списком в java

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() 
     } 
    } 
+1

Вы можете показать код, в котором вы перебираете список? – rogeriopvl

+0

Я добавил код, в который я перебираю список – 2009-06-21 16:17:41

+0

Вы можете позволить запросу базы данных удалить дубликаты, чтобы вам не пришлось иметь дело с ними в вашем Java-коде. Как правило, все, что вы делаете в базе данных, вероятно, будет намного более эффективным. – rich

ответ

3
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; 
} 

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

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

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

3

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

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

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

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

1

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

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

EDIT: Теперь, когда я вижу, что вы редактировали свой вопрос.

Как ваш список отсортирован (по ССН я полагаю)

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, а затем использовать его как показано ниже.

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

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

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. 

И последнее, но не в последнюю очередь, вы должны переопределить хэш-код() и Equals (метод) на людей класса.

, например

public void int hashcode(){ 

    return 3*this.reason.hascode(); 

} 
+0

в вашем решении для отсортированного списка .. где я добавлю объект person в новый список? Если я добавлю его в «else», мне нужно как-то обновить объект в «if» ... – 2009-06-21 18:40:51

5

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

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

Это может означать, что поля Person объекта ssn и terminationReason могут быть выбраны как ключ и значение соответственно. (И эти поля будут считать 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 является хорошим выбором, так как он не позволяет дублировать пары ключ/значение. Это автоматически устранит любые повторяющиеся причины, данные одному конкретному человеку.

+0

+1 Точно. Я собирался опубликовать свой собственный ответ Multimap, но сейчас я это пропущу. :) Хотя я бы использовал StringUtils.join() из Apache Commons Lang для списка, разделенного запятыми. (И упоминаем, что, возможно, объектно-реляционное сопоставление может быть пересмотрено вообще - объект в Java, представляющий человека, должен иметь все причины в нем ...) – Jonik

+0

@Jonik, спасибо за указатель на StringUtils.join :) I Я добавил это к ответу. (Я знал, что должен быть лучший способ, чем делать это вручную.) Кроме того, я также согласен с тем, что сам объект Person должен содержать несколько причин, чем наличие нескольких объектов Person для одного человека. – coobird

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