簡體   English   中英

如何從列表中存儲的對象中獲取特定字段值的列表?

[英]How to get a list of specific fields values from objects stored in a list?

假設我有一個對象列表,其中包含兩個字段field1field2 ,兩者都是String類型。

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

幸運的是,您可以使用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

試試這個:

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

LambdaJ允許訪問沒有顯式循環的集合,因此不要讓更多的代碼行自己迭代列表,而是讓LambdaJ去做。

對象是對存儲器地址的引用。 然后,此對象的字段是對其他內存地址的其他引用。 因此,對象列表是引用列表。 因此,列表不可能直接訪問對象字段(引用給出的引用)。 最簡潔的答案是不。

注意:無論如何,你會找到一個能夠滿足您需求的API,它仍然會在內部循環。

java作為一種語言,JDK庫都沒有做你想做的事。 您可以使用LambdaJ或等待預期包含lambda表達式的Java 8。

要看...

...你的問題是否avoiding iterating over the collection

  • 在呼叫點的易於實施方面
  • 或者 在算法復雜性方面

具體來說,你的意思是:

  • 你不想自己輸入一個迭代構造 (只需使用一個便利庫),
  • 或者你真的想要一些能在O(1)中自動神奇地返回元素而不需要處理它們 (並且具有完美訪問權限)的東西?

請參閱下面的解決方案和選項。


使用便利庫

如果它是第一個,那么請查看Google Guava,LambdaJ,FunctionalJava或其他實現基本功能構造的庫,並允許您在一些富有表現力的調用中執行您想要的操作。 但請記住,這些可以做到錫上的內容:它們將過濾,收集或轉換集合,並將迭代其元素來執行此操作。

例如:

  • 谷歌番石榴

     Set<String> strings = buildSetStrings(); Collection<String> filteredStrings = Collections2.filter(strings, Predicates.containsPattern("^J")); 
  • 功能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產生影響(最有可能通過定義用於元素類型的超級接口),或者需要相當復雜的實現如果您希望此集合是通用的,則動態地解析成員(最有可能通過使用反射)。

古老的問題,但我想看看我是否可以改進類似的解決方案。

您可以實現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%的你需要一個輕量級適配器的情況。

是!! 這是可能的。 但你必須做一些彎曲的工作。

  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. 將warpped數據轉換到另一個列表。

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

     for(storeTables item:items){ System.out.println(item.getTablename()); } 

TADA !!!! 它只會打印tablename而不是tabtype;)相信java中沒有什么不可能有任何疑問!!

不,你不能。 您必須遍歷整個列表並從每個對象獲取每個“field1”值。

也許你可以用這種方式創建一個hashmap:

HashMap<String, ArrayList<Object>> map;

關鍵是這個領域。 這樣做時,當您要求HashMap檢索對應於您想要的字段的對象時,該映射將返回一個ArrayList,其中包含具有該字段的所有元素。

沒有迭代,這是不可能的。你可以以某種方式減少迭代,但這是必須的。

在不同的列表中添加記錄的值,並使用一個或兩個迭代器只需打印單獨的值。如下所示:

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

讓對象屬於以下類。

public class Bike {

    String bikeModel;
    Int price;
}

現在有名為BikeList的自行車清單列表

所以現在我們想要上面列表中所有自行車的自行車模型列表。

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

返回bikeList中所有自行車對象的第一個字段的數組列表

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM