简体   繁体   English

利用 Java stream API 从持有可流 collections 本身的对象中检索数据

[英]Leverage Java stream API to retrieve data from objects holding streamable collections themselves

Problem statement问题陈述

In my architecture there are data objects which I intend to display in a structured fashion.在我的架构中,有一些我打算以结构化方式显示的数据对象。 These objects look like this:这些对象看起来像这样:

public class A
{
   private final String a1;

   public A( String a1 )
   {
      this.a1 = a1;
   }

   public String getA1()
   {
      return a1;
   }
}
public class B
{
   private final String b1;
   private final List<A> bList;

   public B( String b1, List<A> list )
   {
      this.b1 = b1;
      this.bList = list;
   }

   public String getB1()
   {
      return b1;
   }

   public List<A> getBList()
   {
      return bList;
   }
}
public class C
{
   private final String c1;
   private final int c2;
   private final List<B> cList;

   public C( String c1, int c2, List<B> list )
   {
      this.c1 = c1;
      this.c2 = c2;
      this.cList = list;
   }

   public String getC1()
   {
      return c1;
   }

   public int getC2()
   {
      return c2;
   }

   public List<B> getCList()
   {
      return cList;
   }
}

So an object C holds some values, as well as a list of objects B and those objects B hold some values of their own as well as respectively a list of objects A , which in turn hold some values themselves.因此 object C包含一些值,以及对象B的列表,这些对象B包含它们自己的一些值以及对象 A 的列表,而对象A本身又包含一些值。

The requirements I am trying to comply with are putting these into a JSON structure and also create a list of objects, where every entry looks like a collection of all of those data properties in a single object .我试图遵守的要求是将这些放入 JSON 结构中,并创建一个对象列表,其中每个条目看起来都像是单个 object 中所有这些数据属性的集合 The latter is supposed to look like this:后者应该是这样的:

public class D
{
   public final String a1;
   public final String b1;
   public final String c1;
   public final int c2;

   public D( String a1, String b1, String c1, int c2 )
   {
      this.a1 = a1;
      this.b1 = b1;
      this.c1 = c1;
      this.c2 = c2;
   }
}

The declared goal is to have those collected in a List<D> .声明的目标是将那些收集在List<D>中。

My solutions so far到目前为止我的解决方案

The JSON structuring was easy to accomplish with Jackson: JSON 结构很容易用 Jackson 完成:

C c = someGetterForC();
ObjectMapper mapper = new ObjectMapper();
mapper.enable( SerializationFeature.INDENT_OUTPUT );
try
{
   return mapper.writeValueAsString( c );
}
catch( JsonProcessingException e )
{
   // do error handling here
}

This gives me a well formatted JSON string and complies with the first requirement.这给了我一个格式良好的 JSON 字符串并符合第一个要求。 For the second requirement I initially used a very trivial approach, ie simply to collect all data in for -loops, thereby creating instances of D and putting them in a list.对于第二个要求,我最初使用了一种非常简单的方法,简单地在for循环中收集所有数据,从而创建D的实例并将它们放入列表中。 This looked somewhat like this:这看起来有点像这样:

List<D> dList = new ArrayList<>();
C c = someGetterForC();
for( B b : c.getCList() )
{
   for( A a : b.getBList() )
   {
      D d = new D( a.getA1(), b.getB1(), c.getC1(), c.getC2() )
      dList.add( d );
   }
}

However I would like to learn to do this using Java-Streams in order to create instances of D , because I am still having trouble with understanding some of its concepts.但是我想学习使用 Java-Streams 来创建D的实例,因为我仍然无法理解它的一些概念。 The struggle I am facing is with我面临的斗争是

  • Streaming the list of objects A after streaming lists of object B在流式传输 object B列表之后流式传输对象列表A
  • Accessing non-list members from A , B and C in the same call and collecting them in instances of D在同一调用中访问来自ABC的非列表成员,并在D的实例中收集它们

Can this be done in a single stream-API call, ie这可以在单个流 API 调用中完成吗,

C c = someGetterForC();
c.stream()
// how to continue?

and if so, does it make sense to do so?如果是这样,这样做有意义吗?

Notes笔记

  • Java 11 is mandatory, the project has currently no access to newer Java data structures Java 11 是强制性的,该项目目前无法访问较新的 Java 数据结构
  • The fact that given the for -loops there will be redundant data in the instances of D is of no concern and intended考虑到for循环,在D的实例中会有冗余数据这一事实是无关紧要的,也是有意为之的

Example例子

Assume there is an object C c_alpha which holds:假设有一个 object C c_alpha包含:

c1 = "car"
c2 = 42;
cList = {b_alpha, b_beta}

Where B b_alpha holds:其中B b_alpha成立:

b1 = "boulder"
bList = {a_alpha}

And B b_beta holds: B b_beta成立:

b1 = "bomb"
bList = {a_beta, a_gamma}

Lastly there are the type A objects left, A a_alpha holds:最后剩下类型A对象, A a_alpha持有:

a1 = "ape"

A a_beta holds: A a_beta持有:

a1 = "andromeda"

And A a_gamma holds: A a_gamma成立:

a1 = "axe"

Then the collected list of objects D that I am trying to get by leveraging the stream-API should look like this:然后,我试图通过利用流 API 获取的对象D的收集列表应如下所示:

{ "42", "car", "boulder", "ape" },
{ "42", "car", "bomb", "andromeda" },
{ "42", "car", "bomb", "axe" },

TL;DR长话短说

Given objects which hold primitive types + strings as members, as well as lists of objects, which in turn hold primitive types + strings as members as well as lists of objects - how to stream them in a single call to retrieve tuples of the primitive types + strings accross all types in a single call?给定将原始类型 + 字符串作为成员的对象,以及对象列表,这些对象又将原始类型 + 字符串作为成员以及对象列表 - 如何在一次调用中 stream 它们以检索原始类型的元组+ 在一次调用中跨所有类型的字符串?

I realize this is hard to properly formulate, the example above should clear things up.我意识到这很难正确表述,上面的例子应该清楚了。

In order to get the same result as with your classical for-loop approach you need to use flatMap .为了获得与经典 for 循环方法相同的结果,您需要使用flatMap Get the list of B s from your object and stream over it, flatmap and get every A for each B by calling getBList() and map the data to a new D object and finally collect to list of D objects.从您的 object 和 stream 中获取B的列表,通过调用getBList()和 map 将数据平面化并获取每个B的每个A到新的D object,最后收集到D对象列表。 Something like below should give you what you are looking for像下面这样的东西应该会给你你正在寻找的东西

C c = someGetterForC();

List<D> dList = c.getCList()
                 .stream()
                 .flatMap(b -> b.getBList()
                                .stream()
                                .map(a -> new D(a.getA1(), b.getB1(), c.getC1(), c.getC2())))
                 .collect(Collectors.toList());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM