【问题标题】:Filtering 2 array composite object elements using java 8 stream使用java 8流过滤2个数组复合对象元素
【发布时间】:2018-09-01 20:14:30
【问题描述】:

我有 2 个数组对象,第一个是复合对象,另一个是简单的对象数组,如果找到匹配,则基于一些比较,创建一个新列表。那将是一个基于条件的过滤列表。我使用 java 1.7 版本做到了这一点,但是如果使用 java-8 使用更少的代码可以实现这一点,请寻求指导。

这是我的代码,它根据条件过滤器创建一个新列表

public static void main(String[] args) throws CloneNotSupportedException {
    String[] accountOid = {"1","2","3","4","5","6","7","8"};
    AccountHoldCompositeObj[] accts = prepare();
    ArrayList<AccountHoldCompositeObj> list = new ArrayList<AccountHoldCompositeObj>(); 
    for (int i = 0; i < accountOid.length; i++) {
        for (int j = 0; j < accts.length; j++) {
            ObjectId oid =  new ObjectId(accountOid[i]);
            if (oid.equals(accts[j].getAccountOid())) {
                AccountHoldCompositeObj anAccount = (AccountHoldCompositeObj) accts[j].clone();                 
                list.add(anAccount);
                break;
            }
        }
    } 

    list.stream().forEach(s->System.out.println(s));
}

private static AccountHoldCompositeObj[] prepare() {
    AccountHoldCompositeObj[] valArr = new AccountHoldCompositeObj[5];
    int k =10;
    for (int i=0;i<50;i++){         
        AccountHoldCompositeObj create = new AccountHoldCompositeObj(); 
        create.setAccountId(Integer.toString(k));//some more elements
        create.setAccountOid(new ObjectId(i)); 
        valArr[i] = create;
        k++;
    }
    return valArr;
}

我尝试在流中转换数组,然后使用过滤器,但不知何故无法准确比较 2 个不同的元素,即:

  1. accountOid[i] of accountOid 数组(简单数组)
  2. accts[j].getAccountOid()AccountHoldCompisiteObj 数组(复合 数组)

【问题讨论】:

    标签: java arrays java-8 java-stream


    【解决方案1】:

    我想您的目标是将内部for-loop 转换为外部for-loop。实际上,您所做的只是将从每个AccountHoldCompositeObject 接收到的ObjectId 对象与一组预定义的String OID 进行比较,作为要比较的ObjectId 的模板。不需要.clone()

    在进入 Stream 之前,我建议先准备好数据,以便流畅、轻松地操作和使用。您想要的最后一个是在 lambda 中执行复杂的转换。做:

    1. 定义一组转换后的 OID 的 Set&lt;ObjectId&gt;StringObjectId)。
    2. 迭代列表并使用预定义Set&lt;ObjectId&gt; 中可用的OID 搜索列表。
    3. 收集剩余的到所需的输出。

    给你:

    Set<ObjectId> idSet = Arrays.stream(accountOid)             // Stream over String[]
                                .map(str -> new ObjectId(str))  // Create ObjectId from each
                                .collect(Collectors.toSet());   // Collect to Set<ObjectId>
    
    List<AccountHoldCompositeObj> list = Arrays
        .stream(accts)                                          // Stream over AccountHoldCompositeObj[]
        .filter(acct -> idSet.contains(acct.getAccountOid()))   // Filter elements by IDs
        .collect(Collectors.toList());                          // Collect to List
    

    【讨论】:

      【解决方案2】:

      有很多 for 循环,我添加了如下新代码。我注释掉了一些行以了解那里发生了什么。

      public static void main(String[] args) {
      
              final List<AccountHoldCompositeObj> accts = prepare();
              Set<ObjectId> setOfAccountObjectId = IntStream.range(1, 8) //Int stream range between 1-8
                      .map(str -> new ObjectId(str)) // Create ObjectId
                      .collect(Collectors.toSet()); // Collect into Set
      
              accts.stream()                                          // Stream for AccountHoldComposite array
                      .filter(acct -> setOfAccountObjectId.contains(acct.getAccountOid()))   // Filter elements by existing ids
                      .collect(Collectors.toList())
                      .forEach(System.out::println);
          }
      
          private static List<AccountHoldCompositeObj> prepare() {
              int k = 10;
              //creating AccountHoldCompositeObj elements between 0-50
              return Stream.iterate(0, m -> m + 1)
                      .limit(50)
                      .map(currentId -> {
                          AccountHoldCompositeObj create = new AccountHoldCompositeObj();
                          create.setAccountId(Integer.toString(k));//some more elements
                          create.setAccountOid(new ObjectId(currentId));
                          return create;
                      })
                      .collect(Collectors.toList());
      
          }
      

      编辑:我为您的for loop 添加了Stream.iterate,它位于0 and 50 之间。

      【讨论】:

      • prepare() 方法给我错误“类型不匹配:无法从 AccountHoldCompositeObj 转换为 int”
      • .map(str->new ObjectId(str)) 给我错误“.collect(Collectors.toSet());”我有什么错误吗,我复制了给定的代码
      • ObjectId 是不是你自己的类?
      • 是的,ObjectId 是我的自定义类。通过使用 Stream.iterate 和 list 作为返回类型来准备方法,此编辑使其工作。谢谢!
      • 在过滤 accts.stream().... 时如果我想根据过滤器设置更多属性,我使用 peek 方法然后收集列表,使用 peek 可以吗?因为这主要用于调试?
      猜你喜欢
      • 2021-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多