java8中Collectors.groupingBy下用Collectors.reducing的疑惑

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java8中Collectors.groupingBy下用Collectors.reducing的疑惑相关的知识,希望对你有一定的参考价值。

在用groupingBy时发现程序没有输出我想要的结果,如下:
List<GrossMarginPredictedDetailDto>list = new ArrayList<GrossMarginPredictedDetailDto>();
GrossMarginPredictedDetailDto a = new GrossMarginPredictedDetailDto();
GrossMarginPredictedDetailDto a1 = new GrossMarginPredictedDetailDto();
GrossMarginPredictedDetailDto a2 = new GrossMarginPredictedDetailDto();
GrossMarginPredictedDetailDto a3 = new GrossMarginPredictedDetailDto();
a.setMatnr("abc");
a1.setMatnr("edf");
a2.setMatnr("abc");
a3.setMatnr("dd");
a.setN_clie1(new BigDecimal("1.5"));
a1.setN_clie1(new BigDecimal("1.5"));
a2.setN_clie1(new BigDecimal("1.4"));
a3.setN_clie1(new BigDecimal("1.0"));
list.add(a);list.add(a1);list.add(a2);list.add(a3);
Map<String, GrossMarginPredictedDetailDto> map1 = list.stream().collect(Collectors.groupingBy(GrossMarginPredictedDetailDto::getMatnr,Collectors.reducing(new GrossMarginPredictedDetailDto(), (x1,x2) ->
if(x1.getN_clie1()==null)
x1.setN_clie1(x2.getN_clie1());
else
x1.setN_clie1(x1.getN_clie1().add(x2.getN_clie1()==null?BigDecimal.ZERO:x2.getN_clie1()));

return x1;
)));
我想实现的效果就是根据matnr属性分组,然后组内求和,但实际输出的却是
dd:5.4
abc:5.4
edf:5.4
感觉像是全局求和了,怎么会这样呢?比如
Map<String, Long> map1 = list.stream().collect(Collectors.groupingBy(GrossMarginPredictedDetailDto::getMatnr,Collectors.counting()));这样子的又是正常组内求总数,有谁知道原因吗

参考技术A 改成下面这样就可以了。
List<GrossMarginPredictedDetailDto> list = new ArrayList<GrossMarginPredictedDetailDto>();
GrossMarginPredictedDetailDto a = new GrossMarginPredictedDetailDto();
GrossMarginPredictedDetailDto a1 = new GrossMarginPredictedDetailDto();
GrossMarginPredictedDetailDto a2 = new GrossMarginPredictedDetailDto();
GrossMarginPredictedDetailDto a3 = new GrossMarginPredictedDetailDto();
a.setMatnr("abc");
a1.setMatnr("edf");
a2.setMatnr("abc");
a3.setMatnr("dd");
a.setN_clie1(new BigDecimal("1.5"));
a1.setN_clie1(new BigDecimal("1.5"));
a2.setN_clie1(new BigDecimal("1.4"));
a3.setN_clie1(new BigDecimal("1.0"));
list.add(a);
list.add(a1);
list.add(a2);
list.add(a3);
Map<String, GrossMarginPredictedDetailDto> map1 = list.stream().collect(Collectors.groupingBy(GrossMarginPredictedDetailDto::getMatnr, Collectors.reducing(new GrossMarginPredictedDetailDto(), (v1, v2) ->
GrossMarginPredictedDetailDto dto = new GrossMarginPredictedDetailDto();
dto.setMatnr(v1 != null ? v1.getMatnr() : v2.getMatnr());
dto.setN_clie1(Optional.ofNullable(v1).map(GrossMarginPredictedDetailDto::getN_clie1).orElse(BigDecimal.ZERO).add(Optional.ofNullable(v2).map(GrossMarginPredictedDetailDto::getN_clie1).orElse(BigDecimal.ZERO)));
return dto;
)));
参考技术B 可以用Java8的Stream来帮助生成集合,举例如下: public static void main(String[] args) // 起始数字 int start = 1; // 生成数字的个数 int end = 100; // 生成1,2,3,4,5100 List list = Stream.iterate(start, item -> item+1).limit(e 参考技术C reducing里面return一个新对象出来,不要return X1。 参考技术D 我也遇到同样的问题了,有大神知道什么原因吗?

java中this的用法?

java中this怎么用

Java关键字this只能用于方法方法体内。当一个对象创建后,Java虚拟机(JVM)就会给这个对象分配一个引用自身的指针,这个指针的名字就是 this。因此,this只能在类中的非静态方法中使用,静态方法和静态的代码块中绝对不能出现this,这在“Java关键字static、final 使用总结”一文中给出了明确解释。并且this只和特定的对象关联,而不和类关联,同一个类的不同对象有不同的this。

package test;
public class ThisTest
private int i=0;
//第一个构造器:有一个int型形参
ThisTest(int i)
this.i=i+1;//此时this表示引用成员变量i,而非函数参数i
System.out.println("Int constructor i——this.i: "+i+"——"+this.i);
System.out.println("i-1:"+(i-1)+"this.i+1:"+(this.i+1));
//从两个输出结果充分证明了i和this.i是不一样的!

// 第二个构造器:有一个String型形参
ThisTest(String s)
System.out.println("String constructor: "+s);

// 第三个构造器:有一个int型形参和一个String型形参
ThisTest(int i,String s)
this(s);//this调用第二个构造器
//this(i);

this.i=i++;//this以引用该类的成员变量
System.out.println("Int constructor: "+i+"/n"+"String constructor: "+s);

public ThisTest increment()
this.i++;
return this;//返回的是当前的对象,该对象属于(ThisTest)

public static void main(String[] args)
ThisTest tt0=new ThisTest(10);
ThisTest tt1=new ThisTest("ok");
ThisTest tt2=new ThisTest(20,"ok again!");

System.out.println(tt0.increment().increment().increment().i);
//tt0.increment()返回一个在tt0基础上i++的ThisTest对象,
//接着又返回在上面返回的对象基础上i++的ThisTest对象!


/*
细节问题注释已经写的比较清楚了,这里不在赘述,只是总结一下,其实this主要要三种用法:
1、表示对当前对象的引用!
2、表示用类的成员变量,而非函数参数,注意在函数参数和成员变量同名是进行区分!其实这是第一种用法的特例,比较常用,所以那出来强调一下。
3、用于在构造方法中引用满足指定参数类型的构造器(其实也就是构造方法)。但是这里必须非常注意:只能引用一个构造方法且必须位于开始!
还有就是注意:this不能用在static方法中!所以甚至有人给static方法的定义就是:没有this的方法!虽然夸张,但是却充分说明this不能在static方法中使用!
说明在什么情况下需要用到this:
第一、通过this调用另一个构造方法,用发是this(参数列表),这个仅仅在类的构造方法中,别的地方不能这么用。
第二、函数参数或者函数中的局部变量和成员变量同名的情况下,成员变量被屏蔽,此时要访问成员变量则需要用“this.成员变量名”的方式来引用成员变量。当然,在没有同名的情况下,可以直接用成员变量的名字,而不用this,用了也不为错,呵呵。
第三、在函数中,需要引用该函所属类的当前对象时候,直接用this。
其实这些用法总结都是从对“this是指向对象本身的一个指针”这句话的更深入的理解而来的,死记不然容易忘记而且容易搞错,要理解!
*/
参考技术A 一、指自己所在的对象。
比如在一个方法中,调用其他对象的变量或方法时,可以使用那个对象的对象名,比如aa.abc();
而调用自己所在对象的方法或变量时,不知道别人给起了什么名,所以直接用this.abc()就可以了。
二、看一个小例子中“this”的用法!

/**

* @author fengzhi-neusoft

*

* 本示例为了说明this的三种用法!

*/

package test;

public class ThisTest

private int i=0;

//第一个构造器:有一个int型形参

ThisTest(int i)

this.i=i+1;//此时this表示引用成员变量i,而非函数参数i

System.out.println("Int constructor i——this.i: "+i+"——"+this.i);

System.out.println("i-1:"+(i-1)+"this.i+1:"+(this.i+1));

//从两个输出结果充分证明了i和this.i是不一样的!



// 第二个构造器:有一个String型形参

ThisTest(String s)

System.out.println("String constructor: "+s);



// 第三个构造器:有一个int型形参和一个String型形参

ThisTest(int i,String s)

this(s);//this调用第二个构造器

//this(i);

/*此处不能用,因为其他任何方法都不能调用构造器,只有构造方法能调用他。

但是必须注意:就算是构造方法调用构造器,也必须为于其第一行,构造方法也只能调

用一个且仅一次构造器!*/

this.i=i++;//this以引用该类的成员变量

System.out.println("Int constructor: "+i+"/n"+"String constructor: "+s);



public ThisTest increment()

this.i++;

return this;//返回的是当前的对象,该对象属于(ThisTest)



public static void main(String[] args)

ThisTest tt0=new ThisTest(10);

ThisTest tt1=new ThisTest("ok");

ThisTest tt2=new ThisTest(20,"ok again!");

System.out.println(tt0.increment().increment().increment().i);

//tt0.increment()返回一个在tt0基础上i++的ThisTest对象,

//接着又返回在上面返回的对象基础上i++的ThisTest对象!





运行结果:

Int constructor i——this.i: 10——11

String constructor: ok

String constructor: ok again!

Int constructor: 21

String constructor: ok again!

14

细节问题注释已经写的比较清楚了,总结一下,其实this主要要三种用法:

1、表示对当前对象的引用!

2、表示用类的成员变量,而非函数参数,注意在函数参数和成员变量同名是进行区分!其实这是第一种用法的特例,比较常用,所以那出来强调一下。

3、用于在构造方法中引用满足指定参数类型的构造器(其实也就是构造方法)。但是这里必须非常注意:只能引用一个构造方法且必须位于开始!

还有就是注意:this不能用在static方法中!所以甚至有人给static方法的定义就是:没有this的方法!虽然夸张,但是却充分说明this不能在static方法中使用!本回答被提问者和网友采纳
参考技术B 这个this肯定是用在某个类的方法里吧?呵呵,我们继续往下说。

举个例子:
public class persion

private String name=null;
private int age;

public void setName(String name)
this.name=name;

public String getName()

return name;




在这个类中setName方法中第一个变量用this是为了和本方法的参数this做区别,表示这个name指的是Person这个类的name属性,而不是name参数,如果去掉这个this,执行完这个方法后,Person类的name属性仍然为null
getName方法返回的Person类的name,之所以不用this是因为没有必要,因为编译器会知道这个name就指的是Person的name而不是其他的name(因为找个方法没有name变量和它混淆)。当然,这个方法你也可以显示的使用return this.name,没错。
参考技术C 1. this指当前对象。
当在一个类中要明确指出使用对象变量或函数时加上this引用。如下面例子中:

public class Hello

String s = "Hello";

public Hello(String s)
System.out.println("s = " + s);
System.out.println("1 -> this.s = " + this.s);
this.s = s;
System.out.println("2 -> this.s = " + this.s);


public static void main(String[] args)
Hello x=new Hello("HelloWorld!");



运行结果:

s = HelloWorld!
1 -> this.s = Hello
2 -> this.s = HelloWorld!

在这个例子中,构造函数Hello中,参数s与类Hello的变量s同名,这时直接对s进行操作则是对参数s进行操作。对类Hello的成员变量s进行操作就应该用this进行引用。运行结果的第一行就是直接对构造函数中传递过来的参数s进行打印结果;
第二行是对成员变量s的打印;第三行是先对成员变量s赋传过来的参数s值后再打印,所以结果是HelloWorld!

2. this作为参数传递
当你要把自己作为参数传递给别的对象时如:

public class A
public A()
new B(this).print();


public void print()
System.out.println("Hello from A!");



public class B
A a;
public B(A a)
this.a = a;


public void print()
a.print();
System.out.println("Hello from B!");



运行结果:
Hello from A!
Hello from B!

在这个例子中,对象A的构造函数中,new
B(this)把对象A作为参数传递给了对象B的构造函数。
参考技术D 一、指自己所在的对象。
比如在一个方法中,调用其他对象的变量或方法时,可以使用那个对象的对象名,比如aa.abc();
而调用自己所在对象的方法或变量时,不知道别人给起了什么名,所以直接用this.abc()就可以了。
二、看一个小例子中“this”的用法!

/**

* @author fengzhi-neusoft

*

* 本示例为了说明this的三种用法!

*/

package test;

public class ThisTest

private int i=0;

//第一个构造器:有一个int型形参

ThisTest(int i)

this.i=i+1;//此时this表示引用成员变量i,而非函数参数i

System.out.println("Int constructor i——this.i: "+i+"——"+this.i);

System.out.println("i-1:"+(i-1)+"this.i+1:"+(this.i+1));

//从两个输出结果充分证明了i和this.i是不一样的!



// 第二个构造器:有一个String型形参

ThisTest(String s)

System.out.println("String constructor: "+s);



// 第三个构造器:有一个int型形参和一个String型形参

ThisTest(int i,String s)

this(s);//this调用第二个构造器

//this(i);

/*此处不能用,因为其他任何方法都不能调用构造器,只有构造方法能调用他。

但是必须注意:就算是构造方法调用构造器,也必须为于其第一行,构造方法也只能调

用一个且仅一次构造器!*/

this.i=i++;//this以引用该类的成员变量

System.out.println("Int constructor: "+i+"/n"+"String constructor: "+s);



public ThisTest increment()

this.i++;

return this;//返回的是当前的对象,该对象属于(ThisTest)



public static void main(String[] args)

ThisTest tt0=new ThisTest(10);

ThisTest tt1=new ThisTest("ok");

ThisTest tt2=new ThisTest(20,"ok again!");

System.out.println(tt0.increment().increment().increment().i);

//tt0.increment()返回一个在tt0基础上i++的ThisTest对象,

//接着又返回在上面返回的对象基础上i++的ThisTest对象!





运行结果:

Int constructor i——this.i: 10——11

String constructor: ok

String constructor: ok again!

Int constructor: 21

String constructor: ok again!

14

细节问题注释已经写的比较清楚了,总结一下,其实this主要要三种用法:

1、表示对当前对象的引用!

2、表示用类的成员变量,而非函数参数,注意在函数参数和成员变量同名是进行区分!其实这是第一种用法的特例,比较常用,所以那出来强调一下。

3、用于在构造方法中引用满足指定参数类型的构造器(其实也就是构造方法)。但是这里必须非常注意:只能引用一个构造方法且必须位于开始!

还有就是注意:this不能用在static方法中!所以甚至有人给static方法的定义就是:没有this的方法!虽然夸张,但是却充分说明this不能在static方法中使用!

以上是关于java8中Collectors.groupingBy下用Collectors.reducing的疑惑的主要内容,如果未能解决你的问题,请参考以下文章

java8 新特性2-接口中的默认方法和静态方法

Java8中Lambda表达式详解

java8新特性——简介

如何在java8中愉快地处理日期和时间java8新增了localdate和localtim

掌握Java8 函数式编程-Stream

Java8 Stream流