如何从列表中存储的对象中获取特定字段值的列表?

时间:2012-06-12 12:57:04

标签: java collections

假设我有一个包含两个字段field1field2的对象列表,这两个字段都是字符串类型。

如果可能的话,如何获取所有field1值的列表而不必迭代列表?

12 个答案:

答案 0 :(得分:23)

幸运的是,您可以使用 Java 8 - Streams

执行此操作

假设您有一个名为 YourEntity

的实体
public class YourEntity {

    private String field1;
    private String field2;

    public YourEntity(String field1, String field2) {
        this.field1 = field1;
        this.field2 = field2;
    }

    public void setField1(String field1) {
        this.field1 = field1;
    }

    public void setField2(String field2) {
        this.field2 = field2;
    }

    public String getField1() {
        return field1;
    }

    public String getField2() {
        return field2;
    }
}

使用:

声明 YourEntity 的列表
List<YourEntity> entities = Arrays.asList(new YourEntity("text1", "text2"), new YourEntity("text3", "text4"));

您可以通过以下方式一次性提取 field1 列表:

import java.util.stream.Collectors;

List<String> field1List = entities.stream().map(YourEntity::getField1).collect(Collectors.toList());

或以这种方式

import java.util.stream.Collectors;

List<String> field1List = entities.stream().map(urEntity -> urEntity.getField1()).collect(Collectors.toList());

您也可以使用java 8 :)打印所有项目。

field1List.forEach(System.out::println);

输出

text1
text3

答案 1 :(得分:8)

试试这个:

List<Entity> entities = getEntities();
List<Integer> listIntegerEntities = Lambda.extract(entities, Lambda.on(Entity.class).getFielf1());

LambdaJ允许访问没有显式循环的集合,因此不要让更多的代码行自己迭代列表,而是让LambdaJ去做。

答案 2 :(得分:4)

对象是对内存地址的引用。然后,此对象的字段是对其他内存地址的其他引用。 因此,对象列表是引用列表。因此,列表无法直接访问对象字段(引用给出的引用)。简短的回答是否定的。

注意:无论如何,您都会找到一个能够满足您需求的API,它仍会在内部循环。

答案 3 :(得分:4)

java作为语言和JDK库都没有做你想做的事。您可以使用LambdaJ或等待预计包含lambda表达式的Java 8。

答案 4 :(得分:3)

取决于...

...您的问题是否也引用avoiding iterating over the collection

  • 在呼叫点的易于实施方面
  • 在算法复杂性方面

具体来说,你的意思是:

  • 您不想自己输入迭代构造(只需使用便利库),
  • 或者你真的想要一些可以在O(1)中自动返回元素的东西,而不需要处理它们(并且具有完美的访问权限)?

请参阅下面的解决方案和选项。


使用便利库

如果是第一个,那么请查看Google Guava,LambdaJ,FunctionalJava或其他实现基本功能构造的库,并允许您在一些富有表现力的调用中执行您想要的操作。但请记住,这些做了锡上的内容:它们将过滤,收集或转换集合,并将迭代其元素来执行此操作。

例如:

  • Google Guava

    Set<String> strings = buildSetStrings();  
    Collection<String> filteredStrings =
        Collections2.filter(strings, Predicates.containsPattern("^J"));  
    
  • Functional Java

    Array<Integer> a = array(97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42);
    Array<Integer> b = a.filter(even);
    
  • LambdaJ

    List<Integer> biggerThan3 = filter(greaterThan(3), asList(1, 2, 3, 4, 5));
    

完美访问

如果是第二个,这是不可能的除了,如果您从一开始就构建了所有内容,以便您的对象应该由自定义集合类,可根据插入时的字段值为对象编制索引

它会将它们保存在由所述值索引的桶中,以便您可以将它们作为列表检索或按需设置。

正如下面的评论中所提到的,dounyy的答案是,设计这样的自定义集合可能会对它接受的元素的API产生影响(最有可能通过定义用于元素类型的超级接口),或者需要如果您希望此集合是通用的,那么动态解析成员的相当复杂的实现(很可能通过使用反射)。

答案 5 :(得分:1)

是!!这是可能的。 但你必须做一些弯曲的工作。

  1. 使用必需变量创建内部类。 例如:这里将使用2个变量。(TNAME和TABTYPE)。

     public class storeTables {
            private String tablename = "";
            private String tabletype = "";
            public storeTables(String a, String b)
            {
                this.setTablename(a);
                this.setTabletype(b);
            }
            public void setTablename(String tablename) {
                this.tablename = tablename;
            }
            public String getTablename() {
                return tablename;
            }
            public void setTabletype(String tabletype) {
                this.tabletype = tabletype;
            }
            public String getTabletype() {
                return tabletype;
            }}
    
  2. 创建上面创建的内部类的列表,不要忘记封装它。

    private List<storeTables> objlist= new ArrayList<storeTables>();
    
  3. 将存储的值作为内部类对象获取。

    String Query="SELECT * FROM TAB";
    while(rs.next())
    {
    String tname=rs.getString("TNAME");
    String tabtype=rs.getString("TABTYPE");
    getObjlist().add(new storeTables(tname,tabtype));
            }
    
  4. 创建DATAMODEL并将列表推送到datamodel

    private DataModel selectableItems= new ListDataModel(objlist);
    
  5. 将变形数据输入另一个列表。

    List<storeTables> items= (List<storeTables>)selectableItems.getWrappedData();
    
  6. 最后!!!打印数据。

    for(storeTables item:items){
    System.out.println(item.getTablename());
        }
    
  7. TADA !!!!它只会打印tablename而不是tabtype;) 相信java中没有什么是不可能的 任何疑惑!!

答案 6 :(得分:1)

古老的问题,但我想看看我是否可以改进类似的解决方案。

您可以实现List<String>接口而无需创建充实的ArrayList<String>,因此不会迭代父对象。

final List<Entity> entities = getEntities()
final List<String> field1 = new AbstractList() {
    public String get(int index) {
        return entities.get(index).getField1();
    }
    public int size() {
        return entities.size();
    }
}

它为您提供了一个List而不迭代父对象。

随机访问派生的List<String>将与对基础List<Entity>的随机访问一样昂贵;如果您正在使用不提供快速随机访问的List<Entity>实现,您可能需要跳过几个环节(即实现List<String>的更多方法。但这应该适用于99%的情况下你需要一个轻量级适配器。

答案 7 :(得分:0)

不,你不能。您必须遍历整个列表并从每个对象获取每个“field1”值。

答案 8 :(得分:0)

也许你可以用这种方式创建一个hashmap:

HashMap<String, ArrayList<Object>> map;

关键是该领域。 这样做时,当你要求HashMap检索对应于你想要的字段的对象时,地图会返回一个ArrayList,其中包含具有该字段的所有元素。

答案 9 :(得分:0)

没有迭代,这是不可能的。你可以以某种方式减少迭代,但这是必须的。

答案 10 :(得分:0)

在不同的列表中添加记录的值,并使用一个或两个迭代器简单地打印 单独的值。如下:

rs=st.executeQuery("select * from stu");
List data=new ArrayList();
List data1=new ArrayList();
while(rs.next())
{
   data.add(rs.getString(1));
   data1.add(rs.getString(2));
}
Iterator it=data.iterator();
Iterator it1=data1.iterator();
while(it1.hasNext())
{
   System.out.println(" "+it.next()+"  "+it1.next());
}

答案 11 :(得分:0)

让该对象属于以下类。

public class Bike {

    String bikeModel;
    Int price;
}

现在有一个名为bikeList的自行车列表,类型为List

因此,现在我们需要以上列表中所有自行车的自行车型号列表。

bikeList.map{ Bike b -> b.bikeModel }.toCollection(arrayListOf())

返回bikeList中所有自行车对象的第一个字段的数组列表