简体   繁体   English

将列表中的项目分组并汇总所有其他 Android 字段,在 recyclerview 中显示结果

[英]Group items in a List and sum all other fields Android, Show the result in recyclerview

I have a Firebase database which has this structure我有一个具有这种结构的 Firebase 数据库

{
  "foo" : {
    "data" : {
      "2019-12-01" : [ {
        "item1" : 8,
        "item2" : 16,
        "name" : "user1"
      }, {
        "item1" : 9,
        "item2" : 18,
        "name" : "user2"
      } ],
      "2019-12-02" : [ {
        "item1" : 2,
        "item2" : 26,
        "name" : "user1"
      }, {
        "item1" : 6,
        "item2" : 6,
        "name" : "user2"
      } ]
    }
  }
}

I'm filling a recyclerviewer in the main activity in a very simple way:我正在以一种非常简单的方式在主要活动中填充一个recyclerviewer

public class MainActivity extends AppCompatActivity {

    RecyclerView recyclerView;

    private RecyclerView.LayoutManager layoutManager;
    private Adapter adapter;

    final List<Model> tempList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        recyclerView = findViewById(R.id.simpleRecycler);

        layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setHasFixedSize(true);

        Query statsRef = FirebaseDatabase.getInstance()
                .getReference("foo")
                .child("data")
                .orderByKey()
                .startAt("2019-12-01")
                .endAt("2019-12-02");

        // Read from the database
        statsRef.addValueEventListener(new ValueEventListener() {
            @RequiresApi(api = Build.VERSION_CODES.N)
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                for (DataSnapshot itemSnapshot : dataSnapshot.getChildren()){
                    for (int i = 0; i < 2; i++) {
                        Model model = itemSnapshot.child(String.valueOf(i)).getValue(Model.class);
                        tempList.add(model);
                    }
                }

                adapter = new Adapter(tempList);
                recyclerView.setAdapter(adapter);
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {
            }
        });
    }
}

And the adapter is:适配器是:

public class Adapter extends RecyclerView.Adapter {

    List<Model> models;

    public Adapter(List<Model> models) {
        this.models = models;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.simple_row, parent, false);

        return new ViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        ViewHolder vh = (ViewHolder)holder;

        vh.name.setText(models.get(position).getName());
        vh.item1.setText(String.valueOf(models.get(position).getItem1()));
        vh.item2.setText(String.valueOf(models.get(position).getItem2()));
    }

    @Override
    public int getItemCount() {
        return models.size();
    }
}

The result is a table like this:结果是这样的表:

+-------+---+----+
| user1 | 8 | 16 |
+-------+---+----+
| user2 | 9 | 18 |
+-------+---+----+
| user1 | 2 | 26 |
+-------+---+----+
| user2 | 6 |  6 |
+-------+---+----+

The problem is that I want to group the list by the name and then sum all the other relative fields like below问题是我想按名称对列表进行分组,然后对所有其他相关字段求和,如下所示

+-------+----+----+
| user1 | 10 | 42 |
+-------+----+----+
| user2 | 15 | 24 |
+-------+----+----+

I have tried with no success:我试过没有成功:

tempList.stream().collect(Collectors.groupingBy(Model::getName))
                    .entrySet().stream()
                    .collect(Collectors.toMap(x -> {
                        int item1 = x.getValue().stream().mapToInt(Model::getItem1).sum();
                        int item2 = x.getValue().stream().mapToInt(Model::getItem2).sum();

                        return new Model(x.getKey(), item1, item2);

                    }, Map.Entry::getValue));

I've added the above code above before setting the adapter to the recyclerviewer.在将适配器设置为 recyclerviewer 之前,我已经添加了上面的代码。

Any help, please?请问有什么帮助吗?

You can use a Collectors.toMap operation with a mergeFunction defined to perform the aggregation such as:您可以使用Collectors.toMap操作和定义的mergeFunction来执行聚合,例如:

List<Model> output = new ArrayList<>(tempList.stream()
        .collect(Collectors.toMap(Model::getName, Function.identity(),
                Model::mergeSimilarNames))
        .values()); // interested in merged output 

where the merge function could be defined within Model class as:其中合并函数可以在Model类中定义为:

static Model mergeSimilarNames(Model one, Model two) {
    return new Model(one.getName(), one.getItem1() + two.getItem1(), one.getItem2() + two.getItem2());
}

To relate this with your existing approach, you need a reducing operation after grouping the elements, such as:要将其与您现有的方法相关联,您需要在对元素进行分组后进行归约操作,例如:

Map<String, Optional<Model>> grouping = tempList.stream()
        .collect(Collectors.groupingBy(Model::getName,
                Collectors.reducing(Model::mergeSimilarNames)));

But then you are only interested in getting the final view as the List<Model> amongst the value of above Map , hence your resultant code would be in such case :但是,您只对在上述Map的值中将最终视图作为List<Model>感兴趣,因此您的结果代码将在这种情况下:

List<Model> output = tempList.stream()
        .collect(Collectors.groupingBy(Model::getName,
                Collectors.reducing(Model::mergeSimilarNames)))
        .values().stream()
        .filter(Optional::isPresent)
        .map(Optional::get)
        .collect(Collectors.toList());

But do note, toMap(f1,f2,f3) is preferred over groupingBy(f1, reducing(f2,f3)) .但请注意, toMap(f1,f2,f3)优于groupingBy(f1, reducing(f2,f3)) , toMap(f1,f2,f3) groupingBy(f1, reducing(f2,f3))

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

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