前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java8真不用再搞循环了?

Java8真不用再搞循环了?

作者头像
ImportSource
发布2018-04-03 13:09:44
4.4K0
发布2018-04-03 13:09:44
举报
文章被收录于专栏:ImportSourceImportSource

Java8以后真的不用循环了?真的不用了?

好吧,本文分享的内容是java8之前和java8之后一些代码的不同写法,我们会先介绍java8之前和java8之后不同的写法,然后我们会对二者进行性能测试,得出性能测试对比报告。最后会做一个简单的总结。涉及到java8的内容主要是stream。

好,现在开始。

前后写法对比

List<String> 变为大写

有一个问题:现在有5个字母的数组。要求把这五个字母全部变为大写。

你会怎么写?在java8之前,你也许会这样写:

代码语言:javascript
复制
List<String> alpha = Arrays.asList("a", "b", "c", "d");

//Before Java8
List<String> alphaUpper = new ArrayList<>();
for (String s : alpha) {
    alphaUpper.add(s.toUpperCase());
}

System.out.println(alpha); //[a, b, c, d]
System.out.println(alphaUpper); //[A, B, C, D]

就是通过for来遍历,然后toUpperCase。

那么在java8下呢?你可以不用这么麻烦了:

代码语言:javascript
复制
// Java 8
List<String> collect = alpha.stream().map(String::toUpperCase).collect(Collectors.toList());
System.out.println(collect); //[A, B, C, D]

而且stream还可以支持任何类型:

代码语言:javascript
复制
// Extra, streams apply to any data type.
List<Integer> num = Arrays.asList(1,2,3,4,5);
List<Integer> collect1 = num.stream().map(n -> n * 2).collect(Collectors.toList());
System.out.println(collect1); //[2, 4, 6, 8, 10]

是不是很方便。

List<T> 转换为 List<String>

接下来我们再看一种情况。就是当我们现在有一个list。然后list里是一个自定义的引用类型。然后我们需要遍历这个引用类型对象中的某个属性。

在java8之前怎么做呢?

代码语言:javascript
复制
class Staff {

   private String name;
   private int age;
   private BigDecimal salary;

   public Staff(String name,int age,BigDecimal salary){
       this.name=name;
       this.age=age;
       this.salary=salary;
   }

    public String getName() {
        return name;
    }

    public Staff setName(String name) {
        this.name = name;
        return this;
    }

    public int getAge() {
        return age;
    }

    public Staff setAge(int age) {
        this.age = age;
        return this;
    }

    public BigDecimal getSalary() {
        return salary;
    }

    public Staff setSalary(BigDecimal salary) {
        this.salary = salary;
        return this;
    }
}
代码语言:javascript
复制
List<Staff> staff = Arrays.asList(
        new Staff("importsource", 30, new BigDecimal(10000)),
        new Staff("messi", 27, new BigDecimal(20000)),
        new Staff("xavi", 33, new BigDecimal(30000))
);

//Before Java 8
List<String> result = new ArrayList<>();
for (Staff x : staff) {
    result.add(x.getName());
}
System.out.println(result); //[importsource, messi, xavi]

在java8之后呢?

代码语言:javascript
复制
//Java 8
List<String> collect = staff.stream().map(x -> x.getName()).collect(Collectors.toList());
System.out.println(collect); //[importsource, messi, xavi]

List<object> 转换为 List<other object>

现在我们再假设一种情况。现在有一个list。然后我们需要这个list里的对象中的属性值一个个拿出来,然后封装到一个新的对象中,然后放入一个新的list。

这个时候java8怎么做的呢?

自然还是循环:

代码语言:javascript
复制
public class BeforeJava8 {

    public static void main(String[] args) {

        List<Staff> staff = Arrays.asList(
                new Staff("importsource", 30, new BigDecimal(10000)),
                new Staff("messi", 27, new BigDecimal(20000)),
                new Staff("xavi", 33, new BigDecimal(30000))
        );

        List<StaffPublic> result = convertToStaffPublic(staff);
        System.out.println(result);

    }

    private static List<StaffPublic> convertToStaffPublic(List<Staff> staff) {

        List<StaffPublic> result = new ArrayList<>();

        for (Staff temp : staff) {

            StaffPublic obj = new StaffPublic();
            obj.setName(temp.getName());
            obj.setAge(temp.getAge());
            if ("importsource".equals(temp.getName())) {
                obj.setExtra("this field is for importsource only!");
            }

            result.add(obj);
        }

        return result;

    }

}
代码语言:javascript
复制
class StaffPublic{

    private String name;
    private int age;
    private String extra;

    public StaffPublic(String name,int age,String extra){
        this.name=name;
        this.age=age;
        this.extra=extra;
    }

    public StaffPublic() {

    }

    public String getName() {
        return name;
    }

    public StaffPublic setName(String name) {
        this.name = name;
        return this;
    }

    public int getAge() {
        return age;
    }

    public StaffPublic setAge(int age) {
        this.age = age;
        return this;
    }


    public String getExtra() {
        return extra;
    }

    public StaffPublic setExtra(String extra) {
        this.extra = extra;
        return this;
    }
}

JAVA8之后的做法:

代码语言:javascript
复制
public class NowJava8 {

    public static void main(String[] args) {

        List<Staff> staff = Arrays.asList(
                new Staff("importsource", 30, new BigDecimal(10000)),
                new Staff("messi", 27, new BigDecimal(20000)),
                new Staff("xavi", 33, new BigDecimal(30000))
        );

      // convert inside the map() method directly.
        List<StaffPublic> result = staff.stream().map(temp -> {
            StaffPublic obj = new StaffPublic();
            obj.setName(temp.getName());
            obj.setAge(temp.getAge());
            if ("importsource".equals(temp.getName())) {
                obj.setExtra("this field is for importsource only!");
            }
            return obj;
        }).collect(Collectors.toList());

        System.out.println(result);

    }

}

ok,上面我们展示了java前后的不同写法。很明显java8新增的stream的写法更加的风骚和简便优雅,至少看起来蛮流行。

那么二者的性能如何呢?现在我们分别对java8之前的循环做法和java8之后的stream进行一个性能测试,看看结果。

fori VS Stream 性能对比

测试用例

代码语言:javascript
复制
public class PerformanceTest {

    public static void main(String[] args) {
        List<com.importsource.java8.streams.Staff> staff = Arrays.asList(
                new com.importsource.java8.streams.Staff("importsource", 30, new BigDecimal(10000)),
                new com.importsource.java8.streams.Staff("messi", 27, new BigDecimal(20000)),
                new com.importsource.java8.streams.Staff("xavi", 33, new BigDecimal(30000))
        );


       // beforeJava8(staff);
       // nowJava8(staff);
        OneTest oneTest = new OneTest("nowJava8", 10000);

        Function function = new Function() {
            public void function(Object args) {
                //beforeJava8(staff);
                nowJava8(staff);
            }
        };
        After after = new After() {
            public void after(Object args) {
            }
        };

        oneTest.setFunction(function);
        oneTest.setAfter(after);
        oneTest.start();
    }

    private static void nowJava8(List<Staff> staff) {
        //Java 8
        List<String> collect = staff.stream().map(x -> x.getName()).collect(Collectors.toList());
        System.out.println(collect); //[importsource, messi, xavi]
    }

    private static void beforeJava8(List<Staff> staff) {
        //Before Java 8
        List<String> result = new ArrayList<>();
        for (Staff x : staff) {
            result.add(x.getName());
        }
        System.out.println(result); //[importsource, messi, xavi]
    }
}

测试报告

Samples: 10000,单线程:

for循环:

代码语言:javascript
复制
#Samples:10000
Average:0.011
C-Average:0
medain:0
10% Line:0
30% Line:0
50% Line:0
90% Line:0
95% Line:0
99% Line:0
Min:0
Max:6
Total:110
Con-Total:158
Tps:63291
Error(%):0.0%
Success(%):100.0%

Java8 stream:

代码语言:javascript
复制
#Samples:10000
Average:0.023
C-Average:0
medain:0
10% Line:0
30% Line:0
50% Line:0
90% Line:0
95% Line:0
99% Line:0
Min:0
Max:85
Total:230
Con-Total:258
Tps:38759
Error(%):0.0%
Success(%):100.0%

Samples:1000,单线程:

for循环:

代码语言:javascript
复制
#Samples:1000
Average:0.027
C-Average:0
medain:0
10% Line:0
30% Line:0
50% Line:0
90% Line:0
95% Line:0
99% Line:0
Min:0
Max:2
Total:27
Con-Total:39
Tps:25641
Error(%):0.0%
Success(%):100.0%

Java8 stream:

代码语言:javascript
复制
#Samples:1000
Average:0.111
C-Average:0
medain:0
10% Line:0
30% Line:0
50% Line:0
90% Line:0
95% Line:0
99% Line:0
Min:0
Max:80
Total:111
Con-Total:123
Tps:8130
Error(%):0.0%
Success(%):100.0%

Samples:100,单线程:

for循环:

代码语言:javascript
复制
#Samples:100
Average:0.05
C-Average:0
medain:0
10% Line:0
30% Line:0
50% Line:0
90% Line:0
95% Line:0
99% Line:0
Min:0
Max:1
Total:5
Con-Total:14
Tps:7142
Error(%):0.0%
Success(%):100.0%

Java8 stream:

代码语言:javascript
复制
#Samples:100
Average:0.93
C-Average:1
medain:0
10% Line:0
30% Line:0
50% Line:0
90% Line:0
95% Line:0
99% Line:0
Min:0
Max:87
Total:93
Con-Total:101
Tps:990
Error(%):0.0%
Success(%):100.0%

总结

手画的一张图,java8中的map reduce的叫法其实就是借鉴了处理大数据的那个MapReduce。java8中的stream和java I/O中的那个stream有一点略微的不同。

I/O的那个stream更像是一个通道。而java8中的stream指的是在数据流转的过程中还包含有动态处理,就像上图中的一样,从输入然后被map分开,然后分拣合并到reduce,然后输出一个你想要的结果。

java8的stream是一种新的编程模型,它为java处理流数据或者说是处理集合提供了更方便的方式,而不像java8之前那么的笨重。

但是,java8之后就真的没必要用循环了吗?当然不是。stream只适合处理那些顺序next执行的逻辑。如果涉及到游标,则还是要用fori的。

关于性能。之前有人说stream性能较差。通过我们上面的测试对比发现,stream确实要比for循环慢不少。

到底是用循环还是stream,还是要看具体的场合。循环性能好,stream处理集合更加的方便友好。二者看起来都有各自的优势。

也许在对性能要求敏感的场景下,循环可能是个不错的选择。除此之外,可以去尝试下更加方便友好的stream。

------------

代码放到git 上了,点击“阅读原文”获取。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-04-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ImportSource 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档