Java8-为什么选择java8

Java的演变过程

Java从头到尾都是被设计成为一门面向对象的语言,所以时间长了,它就积累了很多的有用的库。从头开始,他就拥有多线程处理的能力。最重要的是Java里面有两个非常强大非常超前的两个概念:jvm和Java字节码。

Java虚拟机( JVM)及其字节码可能会变得比Java语言本身更重要,而且对于某些应用来说, Java可能会被同样运行在JVM上的竞争对手语言(如Scala或Groovy)取代 。

但是,编程语言生态系统的气候正在变化。程序员越来越多地要处理所谓的大数据(数百万兆甚至更多字节的数据集),并希望利用多核计算机或计算集群来有效地处理。意味着需要使用并行处理——Java以前对此并不支持。

Java 8对于程序员的主要好处在于它提供了更多的编程工具和概念,能以更快,更重要的是能以更为简洁、更易于维护的方式解决新的或现有的编程问题。

语言需要不断改进以跟进硬件的更新或满足程序员的期待 。

要坚持下去, Java必须通过增加新功能来改进,而且只有新功能被人使用,变化才有意义。所以,使用Java 8,你就是在保护你作为Java程序员的职业生涯。

Java8的函数式编程

在未使用函数式编程的时候,我们从一个篮子中取出来一个绿色的苹果,需要编写这样的一个函数:

public static List filterGreenApples(List inventory){
   List result = new ArrayList<>();
    for (Apple apple: inventory){
        if ("green".equals(apple.getColor())) {
            result.add(apple);
        }
    }
    return result;
}

当我们要再筛选出重量大于50g的苹果的时候,需要重新写一个方法:

public static List filterHeavyApples(List inventory){
  List result = new ArrayList<>();
     for (Apple apple: inventory){
         if (apple.getWeight() > 150) {
             result.add(apple);
         }
     }
     return result;
 }

这样子比较麻烦,所以Java8新增了函数式编程的语法,再遇到这种函数的时候,我们可以这样写:

public static boolean isGreenApple(Apple apple) {
  return "green".equals(apple.getColor());
}
public static boolean isHeavyApple(Apple apple) {
    return apple.getWeight() > 150;
}
static List filterApples(List inventory, Predicate p) {
    List result = new ArrayList<>();
    for (Apple apple: inventory){
        if (p.test(apple)) {
            result.add(apple);
        }
    }
    return result;
}

要使用这个函数,我们可以这么调用它:

filterApples(inventory, Apple::isGreenApple);
//或者
filterApples(inventory, Apple::isHeavyApple);

我们发现,在传递方法作为参数的时候,需要先定义一个谓词(方法),这样的话,也是比较麻烦的一件事情。所以Java8的新语法引入了lambda(匿名函数)表达式来防止这种不够简单的做法:

filterApples(inventory, (Apple a) -> "green".equals(a.getColor()) );
//或者
filterApples(inventory, (Apple a) -> a.getWeight() > 150 );
//甚至
filterApples(inventory, (Apple a) -> a.getWeight() < 80 || "brown".equals(a.getColor()) );
//再甚至,省去定义filterApples方法,直接使用库方法filter
filter(inventory, (Apple a) -> a.getWeight() > 150 );

通过这种写法,我们的代码优雅(少)了很多,看起来也很直观。但是,当传递的方法比较复杂,代码比较多时,我们尽量还是定义一个名字比较直观的方法作为参数传进来的比较好。(ps:作为一个优秀的攻城狮,要保证我们的代码质量)

你可能以为对Java8的函数编程特性就此结束了,但是,很遗憾,最优秀的还在最后面:流Streams。通过函数式编程结合Streams的使用,我们可以充分利用好CPU的多核特性,完成对资源的充分利用,它有一套函数式程序员熟悉的、类似于filter的操作,比如map、 reduce,还有我们接下来要讨论的在Collections和Streams之间做转换的方法。

Java8的Streams

Java8中的Streams可以帮助我们更好的对集合进行处理。比如我们要从一个列表中筛选金额较高的交易,然后按照货币进行分组。在Java8之前,我们可能需要这么写:

Map<Currency, List<Transaction>> transactionsByCurrencies = new HashMap<>();
for(Transaction transaction:transactions){
    if(transaction.getPrice()>1000){
        Currency currency=transaction.getCurrency();
        List<Transaction> transactionsForCurrency=
                transactionsByCurrencies.get(currency);
        if(transactionsForCurrency==null){
            transactionsForCurrency=new ArrayList<>();
            transactionsByCurrencies.put(currency,
                    transactionsForCurrency);
        }
        transactionsForCurrency.add(transaction);
    }
}

这段代码有很多套路的写法,好几个if判断导致我们没有办法直观的理解这段代码是做什么的。如果使用streams后,我们可以这样写:

Map<Currency, List<Transaction>> transactionsByCurrencies =
        transactions.stream()
                .filter((Transaction t) -> t.getPrice() > 1000)
                .collect(groupingBy(Transaction::getCurrency));

在理解了streams的用法以后,这段代码的意思就会非常容易读懂。当然,streams并不只是改变了代码的呈现方式,在底层,streams api处理数据的方式与传统的单线程代码并不相同。在之前的代码中,我们会用到for-each来对集合进行迭代,这种方法也叫外部迭代;而在有了streams api之后,根本用不着操心循环的事情,数据处理完全是在库内部进行的,这种方法也叫内部迭代。

在进行内部迭代的时候,我们需要知道,streams api会自动利用cpu的多核特性,充分利用CPU的计算资源进行计算。要使用多核,那就涉及到了并行编程。在以往的代码中,并行编程是一件不容易的事情,因为线程间会涉及到共享变量的同时访问和更新,如果没有协调好,数据可能会被意外改变。代码如下:

public class AddTest implements Runnable {
    private static int i = 0;

    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        AddTest test = new AddTest();
        for (int i = 0; i < 10; i++) {
            exec.execute(test);
        }
        exec.shutdown();
    }

    @Override
    public void run() {
        i++;
        Thread.yield();
        System.out.println(i);
    }
}

Java 8也用Stream API( java.util.stream)解决了这两个问题:集合处理时的套路和晦涩,以及难以利用多核。这样设计的第一个原因是,有许多反复出现的数据处理模式,类似于前一节所说的filterApples或SQL等数据库查询语言里熟悉的操作,如果在库中有这些就会很方便:根据标准筛选数据(比如较重的苹果), 提取数据(例如抽取列表中每个苹果的重量字段),或给数据分组(例如,将一个数字列表分组,奇数和偶数分别列表)等。第二个原因是,这类操作常常可以并行化。例如,如图1-6所示,在两个CPU上筛选列表,可以让一个CPU处理列表的前一半,第二个CPU处理后一半,这称为分支步骤(1)。 CPU随后对各自的半个列表做筛选(2)。最后(3),一个CPU会把两个结果合并起来( Google搜索这么快就与此紧密相关,当然他们用的CPU远远不止两个了)。 -<<Java8实战>>

下面我们体验一下如何利用Stream和Lambda表达式顺序或并行的从一个列表里筛选比较重的苹果:

//顺序处理:
List<Apple> heavyApples = inventory
        .stream()
        .filter((Apple a) -> a.getWeight() > 150)
        .collect(toList());
//并行处理:
List<Apple> heavyApples = inventory
        .parallelStream()
        .filter((Apple a) -> a.getWeight() > 150)
        .collect(toList());

可以看到,使用stream可以大大的减少代码量,增加代码的可读性,方便的控制并发编程。好处多多。

如何利用Java8中的默认方法功能

Java 8中加入默认方法主要是为了支持库设计师,让他们能够写出更容易改进的接口。 我们都知道,Java8之前,如果在接口里面定义了一个方法,那么实现这个接口的方法就必须实现该接口的所有方法,否则,编译就不会通过。而要实现上面的List中的stream和parallelStream方法,就需要在List或者它的父类Conllection中实现这些方法。如果按照之前的需要在实现类中实现接口的所有方法,那么这将会成为我们这些程序员的噩梦。

让我们放心的是,Java8引入了默认方法:以后在接口中可以直接写出来方法体作为默认的方法了,实现这个接口的类不用必须实现已经实现默认方法的方法了。例如: 在Java 8里,你现在可以直接对List调用sort方法。它是用Java 8 List接口中如下所示的默认方法实现的,它会调用Collections.sort静态方法:

default void sort(Comparator<? super E> c) {
    Collections.sort(this, c);
}

这意味着List的任何实体类都不需要显式实现sort,而在以前的Java版本中,除非提供了sort的实现,否则这些实体类在重新编译时都会失败。 因为这会导致多重继承的问题,所以java8中才用了一些限制来避免出现类似于C++中的菱形继承问题。

其他使用JVM的编程语言对比

与Java运行在jvm虚拟机上一样,Scala语言也是运行在jvm上的,它在有些方面有赶超java的趋势。

现在我们知道了java8中新引进来的思想有:将方法和lambda作为一等值;以及在没有可变共享状态时,函数或方法可以有效、安全的并行执行。这两个思想在Stream里面都用到了。

另外,对null的处理,Java8中引入了optional类来进行处理。另外Java8也引入了Scala中的模式匹配的概念。

总结一下:
1、 请记住语言生态系统的思想,以及语言面临的“要么改变,要么衰亡”的压力
2、 函数是一等值;记得方法如何作为函数式值来传递,还有Lambda是怎样写的
3、 Java 8中Streams的概念使得Collections的许多方面得以推广,让代码更为易读,并允许并行处理流元素
4、 可以在接口中使用默认方法,在实现类没有实现方法时提供方法内容
5、 其他来自函数式编程的有趣思想,包括处理null和使用模式匹配

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: VS Code配置Java 8的步骤如下: 1. 首先,确保已经安装了Java 8开发工具包(JDK)。可以在Oracle官方网站下载并安装最新的Java 8 JDK。 2. 打开VS Code,并安装Java插件。在VS Code的扩展商店中搜索并安装Microsoft提供的Java拓展。 3. 点击VS Code的菜单栏中的“文件”(File),选择“首选项”(Preferences),再选择“设置”(Settings)来打开设置页面。 4. 在设置页面中搜索“java.home”,找到“Java: Home”选项。 5. 点击“编辑设置”(Edit in settings.json),将JSON文件中的该选项修改为Java 8 JDK的安装路径。例如,可以将值改为类似于“C:\Program Files\Java\jdk1.8.0_301”的路径。 6. 保存设置文件,关闭并重新打开VS Code以使更改生效。 7. 现在,VS Code已经配置为使用Java 8 JDK。可以创建和编写Java项目,并使用Java 8的特性。 补充说明:确保在编辑器中创建和保存Java文件时,文件扩展名为“.java”。可以使用VS Code的编译和运行功能来编译和运行Java代码。 需要注意的是,以上步骤是按照最常见的配置方法进行说明的。由于个人电脑环境和操作系统的差异,步骤可能会略有不同,但基本原理是一致的。如果遇到问题,可以参考VS Code官方文档或向开发者社区寻求帮助。 ### 回答2: VSCode 是一款轻量级的代码编辑器,可以通过几个简单的步骤来配置 Java 8。 首先,我们需要确保已经在电脑上安装了 Java 8 JDK(Java Development Kit)。 接下来,打开 VSCode,点击左侧的扩展图标,搜索并安装 "Java Extension Pack" 扩展。安装完成后,重新启动 VSCode。 然后,打开一个 Java 项目文件夹或者创建一个新的 Java 文件。点击左侧的 "View",然后选择 "Command Palette",或者直接使用快捷键 "Ctrl + Shift + P",在弹出的搜索框中输入 "Java: Configure Java Runtime" 并选择该命令。 在弹出的列表中,我们需要选择 "JDK",然后点击 "Enter"。然后,VSCode 将尝试自动检测已安装的 JDK 版本。如果检测到多个版本的 JDK,我们可以从列表中选择 Java 8 的路径。 如果 VSCode 没有自动检测到 JDK 的路径,我们可以手动指定路径。在弹出的搜索框中输入 "Java: Home" 并点击 "Enter",然后输入 Java 8 JDK 的安装路径。 配置完成后,VSCode 将会使用 Java 8 JDK 运行我们的 Java 代码。我们可以通过点击 "Run" 来执行代码,并且可以在 "Output" 窗口中查看代码的运行结果。 以上就是在 VSCode 中配置 Java 8 的简单步骤。请记住,这只是基本配置,根据你的具体需求可能还需要添加其他的插件或修改相关设置。对于更复杂的 Java 开发项目,可能需要进一步配置构建工具和依赖管理等。但是通过上述步骤,我们可以开始在 VSCode 中使用 Java 8 进行开发了。 ### 回答3: VS Code是一款轻量级的跨平台开源代码编辑器,在配置Java 8时,需要进行以下步骤: 1. 首先,确保已经安装了Java 8 JDK。可以在官网下载安装最新版本的Java 8 JDK,并按照安装向导进行安装。 2. 打开VS Code,在扩展栏中搜索并安装Java Extension Pack插件。这个插件是为了便于在VS Code中开发和调试Java程序而提供的。 3. 在VS Code中,按下Ctrl + Shift + P组合键,打开命令面板。在命令面板中输入“Java: Configure Java Runtime”,选择这个选项并按Enter键。 4. 在弹出的列表中,选择Java”并按Enter键。 5. 在下拉列表中选择已经安装的Java 8 JDK路径,并按Enter键确认。 6. 接下来,VS Code会自动配置Java 8 JDK,并在底部状态栏显示Java的版本号。 7. 如果想要创建一个新的Java项目,在VS Code的文件菜单中选择“打开文件夹”,选择一个合适的位置,并创建一个新的文件夹。 8. 在新的文件夹中,按下Ctrl + Shift + `组合键,打开集成终端。在终端中输入java -version命令,确认Java的版本信息是否显示为Java 8。 9. 确认Java版本无误后,可以在VS Code中创建Java文件,编写和调试Java程序了。 总的来说,配置Java 8在VS Code中比较简单,只需要安装Java 8 JDK并在VS Code中配置即可。同时安装Java Extension Pack插件,可以提供更好的Java开发环境和工具。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值