2012-11-14 15 views
5

Okej, powiedzmy, że mam naprawdę prostą klasę, np.Utwórz listę wartości z obiektów pobierających listę obiektów.

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

Co chciałbym wiedzieć. Biorąc pod uwagę listę Baby's, czy istnieje Java/chłodniej/krótszy sposób w Javie, aby utworzyć tablicę/tablicę z nazwiskami Baby zamiast prostego zapętlania się przez wszystkie dzieci i dodawania ich nazwisk do nowej listy? Odpowiednik tego:

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()); 
} 

... ale chłodniej. Wiesz co mam na myśli?

+2

* Cooler *? Możliwie. Bardziej czytelny i zrozumiały: trudno. Dopóki nie otrzymamy lambd (i uchwytów metod), nie będziemy w stanie napisać o wiele bardziej zwięźle. –

+0

@JoachimSauer Kiedy w języku java zostaną wprowadzone 'lambdas' w ramach oficjalnej dokumentacji? –

+0

@ZagorulkinDmitry java 8 powinien go uwzględnić. Ale znowu był pierwotnie przeznaczony dla java 7: | – amit

Odpowiedz

0

Cóż ... po prostu nie, nie.

Zakładając szukasz czegoś jak

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

Nie ma nic takiego w Javie.

Jednak można zrobić nową klasę to zrobić dla Ciebie:

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

ten sposób można później powiedzieć:

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); 

Które spowodowałoby tylko o najfajniejszych sposób systematyczny odzyskać imiona Baby, które świat kiedykolwiek znał.

+0

Ahah! Właściwie to wyobrażałem sobie coś podobnego do twojego pierwszego zdania ... 'babies.getNames() 's'; : P Ahh, mogę marzyć. edytuj: nadal przyzwyczajaj się do tego "wprowadź środki wyślij!" cecha. Podoba mi się twój pomysł jako alternatywa dla wszystkiego, co super - późniejszy kod wygląda całkiem fajnie! – user891876

3

Można użyć 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); 

Kluczową różnicą jest to, że babyNameswidok oryginalnej listy, na której transformacje są leniwie ruchu. Z dokumentacji:

Funkcja jest stosowana leniwie, wywoływana w razie potrzeby. Jest to konieczne, aby zwrócona lista była widokiem, ale oznacza to, że funkcja zostanie zastosowana wiele razy w przypadku operacji zbiorczych, takich jak List.contains(java.lang.Object) i List.hashCode(). W tym celu do dobrze, funkcja powinna być szybka. Aby uniknąć leniwej oceny, gdy zwrócona lista nie musi być widokiem, skopiuj zwróconą listę na nową wybraną listę.

Oczywiście składnia implementacji Function jest dość gadatliwa - to Java dla ciebie aż do lambd. I zazwyczaj zachować powszechnie używanych funkcji jako stałe, aby uniknąć bałaganu i ponownie instancji w miejscu połączenia:

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

Tak, to nawet więcej kodu, ale jest ukryty i bardziej linkujących. Następnie w miejscu połączenia:

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

Lol tak, to trochę bardziej gadatliwe, niż początkowo szukałem, ale cholernie fajne! Nigdy wcześniej nie słyszałem o tych listach Guawy, a to jest właśnie ten świetny kod, którego szukałem. Dzięki! – user891876

+0

Jeśli uważasz, że teraz jest fajnie, kiedy * będziemy * mieć Lambdas & Co będzie to skrót od 'List babyNames = Lists.transform (babies, Baby # getName);' (składnia może być nieco inna, ale coś takiego). –

0

Chcesz chłodnica sposób to zrobić? Jeśli znasz Spring framework, masz szczęście!

W aplikacjiContext.xml, napisać coś takiego:

<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> 

Oto kod w normalnym Java

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); 

    } 
    } 

Teraz można edytować listę w applicationContext.xml gdy chcesz dodawać/usuwać dowolną nazwę od lista. Nie trzeba twardo kodować wszystkiego.

Można odwoływać się więcej o Spring Framework kolekcji z tego linku: http://www.mkyong.com/spring/spring-collections-list-set-map-and-properties-example/

Lub jeśli po prostu chcesz dowiedzieć się więcej o Spring, tutaj jest to dobry punkt wyjścia: http://www.mkyong.com/tutorials/spring-tutorials/

1

Z GS Collections masz kilka sposobów na zrobienie tego. Możesz użyć zamiennika zastępczego dla ArrayList o nazwie 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(); 
    } 
}); 

Lub możesz użyć ArrayList z klasą narzędzi 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(); 
    } 
}); 

Jeśli nie zależy Ci na kolejności wyników, ale chcesz zezwolić na duplikaty, możesz zamiast tego użyć torby.

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"); 

Jeśli używasz tej funkcji w kółko, możesz ją ustawić jako stałą na lekcji Baby.

Uwaga: Jestem programistą w kolekcjach GS.

Powiązane problemy