5

好的,假设我有一个非常简单的课程,例如

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

现在我想知道什么。给定一个婴儿列表,在 Java 中是否有任何更漂亮/更酷/更短的方法来创建婴儿姓名的数组/数组列表,而不是简单地循环遍历所有婴儿并将他们的名字添加到新列表中?相当于:

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

...但更酷。明白我的意思了吗?

4

5 回答 5

3

你可以使用番石榴的 Lists.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);

此处的关键区别在于延迟执行转换的原始列表babyNames视图。从文档中:

该函数被延迟应用,在需要时调用。这对于返回的列表是视图是必要的,但这意味着该函数将多次应用于批量操作,如 List.contains(java.lang.Object)List.hashCode()。为了使其表现良好,功能应该是快速的。当返回的列表不需要是视图时,为避免延迟评估,请将返回的列表复制到您选择的新列表中。

显然,实现的语法Function相当冗长——在 lambdas 之前,这对你来说都是 Java。我通常将常用函数保留为常量,以避免在调用站点出现混乱和重新实例化:

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

是的,它甚至更多的代码,但它被隐藏起来并且更易于维护。然后在呼叫站点:

List<String> babyNames = Lists.transform(babies, Baby.Functions.getName());
于 2012-11-14T06:37:45.787 回答
1

使用GS Collections,您有几种方法可以做到这一点。您可以使用称为 FastList 的 ArrayList 的插入式替换。

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

或者,您可以将 ArrayList 与 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();
    }
});

如果您不关心结果顺序,但希望允许重复,您可以使用 Bag 代替。

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

如果你一遍又一遍地使用这个函数,你可能想把它作为一个常量放在 Baby 类上。

注意:我是 GS Collections 的开发人员。

于 2012-11-16T17:32:15.073 回答
0

嗯...简单地说,不。

假设你正在寻找类似的东西

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

Java 中没有这样的东西。

但是,您可以创建一个新课程来为您完成:

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

这样,您以后可以说:

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

这将创造出最酷的方式来系统地检索世界上已知的婴儿名字。

于 2012-11-14T06:36:14.770 回答
0

你想要更酷的方式吗?如果您了解 Spring 框架,那么您很幸运!

在 applicationContext.xml 中,编写如下内容:

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

这是普通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);

    }
  }

现在,只要您想从列表中添加/删除任何名称,您就可以在 applicationContext.xml 中编辑列表。无需对所有内容进行硬编码。

您可以从此链接参考有关 Spring 框架集合的更多信息:http ://www.mkyong.com/spring/spring-collections-list-set-map-and-properties-example/

或者,如果您只是想了解更多关于 Spring 的信息,这里是一个很好的起点: http ://www.mkyong.com/tutorials/spring-tutorials/

于 2012-11-14T06:47:00.627 回答
0

在 2014 年 3 月发布 Java 8 之后,引入 Stream API和操作的更酷的方式是这样的:.map.collect

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

List<String> names = babies
    .stream() // Stream<Baby>
    .map(Baby::getName) // Stream<String>; use reference to the getter method
    .collect(Collectors.toList()); // build resulting list of names
于 2021-11-27T20:06:31.173 回答