2012-11-14 11 views
5

Okay, diciamo che ho una classe molto semplice, ad es.Creare un elenco di valori dai getter di un elenco di oggetti

public class Baby { 
    private String Name = "alf"; 
    public String getName() { 
     return Name; 
    } 
} 

Ora quello che mi piacerebbe sapere. Dato un elenco di Baby's, c'è un modo più niftier/cooler/short in Java per creare un array/arraylist dei nomi dei Baby 'piuttosto che un semplice loop di tutti i bambini e aggiungere i loro nomi alla nuova lista? L'equivalente di questo:

ArrayList<Baby> babies = new ArrayList<Baby>(); 
/* some code adding a bunch of babies to the arraylist */ 

ArrayList<String> names = new ArrayList<String>(); 
for (Baby b : babies) { 
    names.add(b.getName()); 
} 

... ma dispositivo di raffreddamento. Sai cosa intendo?

+2

* Dispositivo di raffreddamento *? Possibilmente. Più leggibile e comprensibile: difficilmente. Finché non avremo finalmente lambdas (e handle di metodo) non saremo in grado di scrivere molto più conciso di così. –

+0

@JoachimSauer Quando in Java verrà introdotto 'lambdas' come parte della documentazione ufficiale? –

+0

@ZagorulkinDmitry java 8 dovrebbe includerlo. Ma poi di nuovo, era originariamente previsto per java 7: | – amit

risposta

0

Beh ... semplicemente, no.

Questo è supponendo che si sta cercando qualcosa di simile

ArrayList<String> names = babies.getName(); 

Non c'è niente di simile in Java.

Tuttavia, si potrebbe fare una nuova classe di farlo per voi:

public class BabyNameifier { 

    public BabyNameifier(){} 

    public ArrayList<String> Nameify(ArrayList<Baby> babies) { 
     ArrayList<String> names = new ArrayList<String>(); 
     for (Baby b : babies) { 
      names.add(b.getName()); 
     } 
     return names; 
    } 
} 

In questo modo, in seguito sarà possibile dire:

ArrayList<Baby> babies = new ArrayList<Baby>(); 
/* some code adding a bunch of babies to the arraylist */ 

BabyNameifier babyNameifier = new BabyNameifier(); 
ArrayList<String> names = babyNameifier.Nameify(babies); 

che creerebbe appena circa il modo più cool per sistematicamente recupera i nomi dei bambini che il mondo ha mai conosciuto.

+0

Ahah! In realtà, immaginavo qualcosa di simile alla tua prima affermazione ... 'babies.getNames() 's'; : P Ahh, posso sognare. modifica: ancora abituarsi a questo "invio significa inviare!" caratteristica. Mi piace la tua idea come alternativa a qualcosa di super bello - il codice successivo sembra davvero bello! – user891876

3

Si potrebbe utilizzare Guava'sLists.transform:

Function<Baby, String> getBabyNameFunction = new Function<Baby, String>() { 
    @Override 
    public String apply(Baby baby) { 
     return baby.getName(); 
    } 
}; 

List<String> babyNames = Lists.transform(babies, getBabyNameFunction); 

La differenza chiave qui è che babyNames è una vista della lista originale su cui vengono eseguite le trasformazioni pigramente. Dalla documentazione:

La funzione viene applicata pigramente, richiamata quando necessario. È necessario perché la lista restituita sia una vista, ma significa che la funzione verrà applicata più volte per operazioni di massa quali List.contains(java.lang.Object) e List.hashCode(). Per fare ciò a , la funzione dovrebbe essere veloce. Per evitare una valutazione lenta quando l'elenco restituito non deve necessariamente essere una vista, copiare l'elenco restituito in un nuovo elenco di propria scelta.

Ovviamente la sintassi per l'attuazione del Function è piuttosto verboso - che è Java per voi fino lambda. Io di solito tengo comunemente funzioni usate come costanti per evitare il disordine e ri-creazione di un'istanza presso il sito di chiamata:

public class Baby { 

    ... 

    public static class Functions { 

     private static final Function<Baby, String> GET_NAME = 
       new Function<Baby, String>() { 
        @Override 
        public String apply(Baby baby) { 
         return baby.getName(); 
        } 
       }; 

     private Functions() { } 

     public static Function<Baby, String> getName() { 
      return GET_NAME; 
     } 
    } 
} 

Sì, è ancora più codice, ma è nascosto e più gestibile. Poi al sito di chiamata:

List<String> babyNames = Lists.transform(babies, Baby.Functions.getName()); 
+1

Lol si, è un po 'più prolisso di quanto cercassi originariamente, ma maledettamente bello! Non ho mai sentito parlare di questi elenchi di Guava prima e questo è esattamente il tipo di codice elegante che stavo cercando. Grazie! – user891876

+0

E se pensi che sia bello ora, una volta che * facciamo * avere Lambdas & Co sarà più breve di 'Lista babyNames = Lists.transform (bebè, Baby # getName);' (la sintassi potrebbe essere leggermente diversa, ma qualcosa come questo). –

0

Volete cooler modo per farlo? Se conosci la struttura di primavera, sei fortunato!

In applicationContext.xml, scrivere qualcosa di simile:

<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> 

<bean id="babyList" class="com.babies.BabyList"> 

    <property name="babyLists"> 
     <list> 
      <bean class="com.babies.Baby"> 
       <property name="name" value="alice" /> 
      </bean> 
      <bean class="com.babies.Baby"> 
       <property name="name" value="bob" /> 
      </bean> 
      <bean class="com.babies.Baby"> 
       <property name="name" value="trudy" /> 
      </bean> 
     </list> 
    </property> 
</bean> 

</beans> 

Ecco il codice in Java normale

package com.babies; 

import org.springframework.context.ApplicationContext; 
import org.springframework.context.support.ClassPathXmlApplicationContext; 

    public class Main { 
     public static void main(String[] args) { 
      ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); 

      BabyList babyList = (BabyList)context.getBean("babyList"); 
      System.out.println(babyList); 

    } 
    } 

Ora è possibile modificare l'elenco nel applicationContext.xml ogni volta che si desidera aggiungere/cancellare qualsiasi nome dal elenco. Non c'è bisogno di codificare tutto.

È possibile fare riferimento più sulla raccolta framework Spring da questo link: http://www.mkyong.com/spring/spring-collections-list-set-map-and-properties-example/

O se semplicemente volete saperne di più su Spring, ecco un buon punto di partenza: http://www.mkyong.com/tutorials/spring-tutorials/

1

Con GS Collections si dispone di un un paio di modi per farlo. È possibile utilizzare la sostituzione drop-in per ArrayList chiamato FastList.

MutableList<Baby> babies = FastList.newList(); 
/* some code adding a bunch of babies to the fastlist */ 

MutableList<String> names = babies.collect(new Function<Baby, String>() { 
    public String valueOf(Baby baby) { 
     return baby.getName(); 
    } 
}); 

Oppure è possibile utilizzare ArrayList con la classe di utilità ListIterate.

ArrayList<Baby> babies = new ArrayList<Baby>(); 
/* some code adding a bunch of babies to the arraylist */ 

List<String> names = ListIterate.collect(babies, new Function<Baby, String>() { 
    public String valueOf(Baby baby) { 
     return baby.getName(); 
    } 
}); 

Se non si cura dell'ordine dei risultati, ma si desidera consentire i duplicati, è possibile utilizzare invece una borsa.

MutableList<Baby> babies = FastList.newList(); 
/* some code adding a bunch of babies to the fastlist */ 

MutableBag<String> names = babies.collect(new Function<Baby, String>() { 
    public String valueOf(Baby baby) { 
     return baby.getName(); 
    } 
}, HashBag.<String>newBag()); 

int numberOfBabiesNamedXYZ = names.occurrencesOf("XYZ"); 

Se si utilizza questa funzione più volte, si consiglia di impostarla come costante sulla classe Baby.

Nota: sono uno sviluppatore di GS Collections.

Problemi correlati