一、Java 虚拟机语言无关性

在正常情况下,我们肯定会认为 Java 虚拟机是用于运行 Java 语言的,其实这么说并不能说是错误,但是也不完全对,这是因为 Java 虚拟机实际上运行的是特定的二进制字节码文件。实际上 Java 虚拟机和某种语言并没有必然的关联,因为不管什么语言只要能够编译成字节码文件,并符合 Java 虚拟机规范,那么 Java 虚拟机就可以加载该字节码文件,并且执行字节码文件中的指令。

JVM 支持的语言: ClojureJRubyGroovyScalaJavaScriptKotlin、…
在这里插入图片描述

因此,每种语言只要编译成符合 Java 虚拟机规范的字节码文件,就可以使用 Java 虚拟机运行指定语言的代码。
在这里插入图片描述

二、Java项目引入Groovy

<dependencies>
   <dependency>
       <groupId>org.apache.groovy</groupId>
       <artifactId>groovy</artifactId>
       <version>${groovy.version}</version>
   </dependency>
</dependencies>

<build>
	<plugins>
	    <plugin>
	        <groupId>org.codehaus.gmavenplus</groupId>
	        <artifactId>gmavenplus-plugin</artifactId>
	        <version>${gmavenplus-plugin.version}</version>
	        <executions>
	            <execution>
	                <goals>
	                    <goal>addSources</goal>
	                    <goal>addTestSources</goal>
	                    <goal>generateStubs</goal>
	                    <goal>compile</goal>
	                    <goal>generateTestStubs</goal>
	                    <goal>compileTests</goal>
	                    <goal>removeStubs</goal>
	                    <goal>removeTestStubs</goal>
	                </goals>
	            </execution>
	        </executions>
	    </plugin>
	</plugins>
</build>

<properties>
    <groovy.version>4.0.21</groovy.version>
    <gmavenplus-plugin.version>3.0.2</gmavenplus-plugin.version>
</properties>

三、Java与Groovy集合

https://www.groovy-lang.org/differences.html
groovy语法非常简洁

1.多行文本字符串

java8之前,如果要将多行字符串引入代码中,会非常丑陋。

{
    "employees":[
      { "firstName":"John", "lastName":"Doe" },
      { "firstName":"Anna", "lastName":"Smith" },
      { "firstName":"Peter", "lastName":"Jones" }
    ]
}
<employees>
  <employee>
    <firstName>John</firstName>
    <lastName>Doe</lastName>
  </employee>
  <employee>
    <firstName>Anna</firstName> 
    <lastName>Smith</lastName>
  </employee>
  <employee>
    <firstName>Peter</firstName> 
    <lastName>Jones</lastName>
  </employee>
</employees>

但groovy是很理想的选择,比如Constants.groovy:

package com.baeldung.demo
/**
 * 常量
 * @author duhongming
 * @see
 * @since 1.0.0
 */
class Constants {
    public static final String JSON_DEMO = """
{
    "employees":[
      { "firstName":"John", "lastName":"Doe" },
      { "firstName":"Anna", "lastName":"Smith" },
      { "firstName":"Peter", "lastName":"Jones" }
    ]
}
"""

    public static final String XML_DEMO = """
<employees>
  <employee>
    <firstName>John</firstName>
    <lastName>Doe</lastName>
  </employee>
  <employee>
    <firstName>Anna</firstName> 
    <lastName>Smith</lastName>
  </employee>
  <employee>
    <firstName>Peter</firstName> 
    <lastName>Jones</lastName>
  </employee>
</employees>
"""
}

测试类:GroovyConstantsTest.java

package com.baeldung.demo;

import org.junit.Test;

/**
 * Groovy 常量测试
 *
 * @author duhongming
 * @see
 * @since 1.0.0
 */
public class GroovyConstantsTest {
    @Test
    public void testJsonDemo() {
        System.out.println(Constants.JSON_DEMO);
    }

    @Test
    public void testXMLDemo() {
        System.out.println(Constants.XML_DEMO);
    }
}

2.更为简洁的lambda表达式

使用groovy建立User实体类,看看是不是很简洁

package com.baeldung.demo
/**
 * 用户
 * @author duhongming
 * @see
 * @since 1.0.0
 */
class User {
    private String name
    private Boolean male
    private String address

    User(String name, Boolean male, String address) {
        this.name = name
        this.male = male
        this.address = address
    }

    String getName() {
        return name
    }

    void setName(String name) {
        this.name = name
    }

    Boolean getMale() {
        return male
    }

    void setMale(Boolean male) {
        this.male = male
    }

    String getAddress() {
        return address
    }

    void setAddress(String address) {
        this.address = address
    }

    @Override
    String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", male=" + male +
                ", address='" + address + '\'' +
                '}';
    }
}

GroovyLambdaTest.groovy中单元测试按顺序执行:在类上加上@TestMethodOrder(MethodOrderer.OrderAnnotation.class),在方法上加上@Order(1)

package com.baeldung.demo

import org.junit.jupiter.api.*

/**
 * Groovy Lambda测试
 * @author duhongming
 * @see
 * @since 1.0.0
 */
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class GroovyLambdaTest {
    static List<User> initData() {
        List<User> users = new LinkedList<>()
        users.add(new User("小红", false, "长春"))
        users.add(new User("小丽", false, "黑龙江"))
        users.add(new User("小李", true, "沈阳"))
        users.add(new User("小明", true, "长春"))
        return users
    }

    @Test
    @Order(1)
    @DisplayName("按地址分组")
    void testGroupingBy() {
        List<User> users = initData()
        Map<String, List<User>> userGroupMap = users.groupBy { it.address }
        println(userGroupMap)
    }

    @Test
    @Order(2)
    @DisplayName("按地址分组并获取第一条")
    void testGroupingBy_GetFirst() {
        List<User> users = initData()
        Map<String, User> userGroupMap = users.groupBy { it.address }
                .collectEntries { k, v -> [k, v.get(0)] }
        println(userGroupMap)
    }

    @Test
    @Order(3)
    @DisplayName("按性别分区")
    void testPartitioningBy() {
        List<User> users = initData()
        Map<Boolean, List<User>> userPartitionMap = users.groupBy { it -> it.male }
        println(userPartitionMap)
    }

    @Test
    @Order(4)
    @DisplayName("按性别分区并获取第一条")
    void testPartitioningBy_GetFirst() {
        List<User> users = initData()
        Map<Boolean, User> userPartitionMap = users.groupBy { it -> it.male }
                .collectEntries { k, v -> [k, v.get(0)] }
        println(userPartitionMap)
    }

}

JavaLambdaTest.java中单元测试按顺序执行:在类上加上@TestMethodOrder(MethodOrderer.OrderAnnotation.class),在方法上加上@Order(1)

package com.baeldung.demo;

import org.junit.jupiter.api.*;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import static java.util.stream.Collectors.*;

/**
 * Java Lambda测试
 *
 * @author duhongming
 * @see
 * @since 1.0.0
 */
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class JavaLambdaTest {

    public List<User> initData() {
        List<User> users = new LinkedList<>();
        users.add(new User("小红", false, "长春"));
        users.add(new User("小丽", false, "黑龙江"));
        users.add(new User("小李", true, "沈阳"));
        users.add(new User("小明", true, "长春"));
        return users;
    }

    @Test
    @Order(1)
    @DisplayName("按地址分组")
    public void testGroupingBy() {
        List<User> users = initData();
        Map<String, List<User>> userMap = users.stream().collect(
                groupingBy(User::getAddress, toList())
        );
        System.out.println(userMap);
    }

    @Test
    @Order(2)
    @DisplayName("按地址分组并获取第一条")
    public void testGroupingBy_GetFirst() {
        List<User> users = initData();
        Map<String, User> userMap = users.stream().collect(
                groupingBy(
                        User::getAddress,
                        collectingAndThen(toList(), list -> list.get(0))
                )
        );
        System.out.println(userMap);
    }

    @Test
    @Order(3)
    @DisplayName("按性别分区")
    public void testPartitioningBy() {
        List<User> users = initData();
        Map<Boolean, List<User>> userMap = users.stream().collect(
                partitioningBy(User::getMale, toList())
        );
        System.out.println(userMap);
    }

    @Test
    @Order(4)
    @DisplayName("按性别分区并获取第一条")
    public void testPartitioningBy_GetFirst() {
        List<User> users = initData();
        Map<Boolean, User> userMap = users.stream().collect(
                partitioningBy(
                        User::getMale,
                        collectingAndThen(toList(), list -> list.get(0))
                )
        );
        System.out.println(userMap);
    }
}

测试结果如下:
在这里插入图片描述

四、参考

http://www.mydlq.club/article/125/

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐