Mkyong-中文博客翻译-四-

Mkyong 中文博客翻译(四)

原文:Mkyong

协议:CC BY-NC-SA 4.0

Jackson–将 JSON 数组字符串转换为列表

原文:http://web.archive.org/web/20230101150211/https://www.mkyong.com/java/jackson-convert-json-array-string-to-list/

几个 Jackson 的例子把一个 JSON 数组字符串转换成一个List

 // JSON array string
	// [{"name":"mkyong", "age":37}, {"name":"fong", "age":38}]

	ObjectMapper mapper = new ObjectMapper();
	String json = "[{\"name\":\"mkyong\", \"age\":37}, {\"name\":\"fong\", \"age\":38}]";

	// 1\. convert JSON array to Array objects
	Person[] pp1 = mapper.readValue(json, Person[].class);

	// 2\. convert JSON array to List of objects
	List<Person> ppl2 = Arrays.asList(mapper.readValue(json, Person[].class)); 

pom.xml

 <dependency>
		<groupId>com.fasterxml.jackson.core</groupId>
		<artifactId>jackson-databind</artifactId>
		<version>2.9.8</version>
	</dependency> 

用杰克逊 2.9.8 测试的 PS

1.将 JSON 数组字符串转换为列表

1.1 JSON 数组字符串

 [{"name":"mkyong", "age":37}, {"name":"fong", "age":38}] 

1.2 创建一个对象来映射上述 JSON 字段。

 package com.mkyong;

public class Person {

    String name;
    Integer age;

    //getters and setters
} 

1.3 将 JSON 数组字符串转换成一个List

JacksonArrayExample.java

 package com.mkyong;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class JacksonArrayExample {

    public static void main(String[] args) {

        ObjectMapper mapper = new ObjectMapper();
        String json = "[{\"name\":\"mkyong\", \"age\":37}, {\"name\":\"fong\", \"age\":38}]";

        try {

            // 1\. convert JSON array to Array objects
            Person[] pp1 = mapper.readValue(json, Person[].class);

            System.out.println("JSON array to Array objects...");
            for (Person person : pp1) {
                System.out.println(person);
            }

            // 2\. convert JSON array to List of objects
            List<Person> ppl2 = Arrays.asList(mapper.readValue(json, Person[].class));

            System.out.println("\nJSON array to List of objects");
            ppl2.stream().forEach(x -> System.out.println(x));

            // 3\. alternative
            List<Person> pp3 = mapper.readValue(json, new TypeReference<List<Person>>() {});

            System.out.println("\nAlternative...");
            pp3.stream().forEach(x -> System.out.println(x));

        } catch (IOException e) {
            e.printStackTrace();
        }

    }
} 

输出

 1\. JSON array to Array objects...
Person{name='mkyong', age=37}
Person{name='fong', age=38}

2\. JSON array to List of objects
Person{name='mkyong', age=37}
Person{name='fong', age=38}

3\. Alternative...
Person{name='mkyong', age=37}
Person{name='fong', age=38} 

参考

Tags : jackson json json array list

Jackson——如何忽略空字段

原文:http://web.archive.org/web/20230101150211/https://www.mkyong.com/java/jackson-how-to-ignore-null-fields/

在 Jackson 中,我们可以使用@JsonInclude(JsonInclude.Include.NON_NULL)来忽略null字段。

用杰克逊 2.9.8 测试的 PS

1.Jackson 默认包含空字段

1.1 审查 POJO,以便稍后进行测试。

Staff.java

 public class Staff {

    private String name;
    private int age;
    private String[] position;               
    private List<String> skills;            
    private Map<String, BigDecimal> salary; 

1.2 默认情况下,Jackson 将包含空字段。

JacksonExample.java

 package com.mkyong;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;

public class JacksonExample {

    public static void main(String[] args) {

        ObjectMapper mapper = new ObjectMapper();

        Staff staff = new Staff("mkyong", 38);

        try {

            String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(staff);

            System.out.println(json);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

} 

输出

 {
  "name" : "mkyong",
  "age" : 38,
  "position" : null,
  "skills" : null,
  "salary" : null
} 

要忽略null字段,请将@JsonInclude放在类级别或字段级别。

2.@ JSON include–类级别

Staff.java

 import com.fasterxml.jackson.annotation.JsonInclude;

											//	ignore null fields , class level
@JsonInclude(JsonInclude.Include.NON_NULL) 	//  ignore all null fields
public class Staff {

    private String name;
    private int age;
    private String[] position;              
    private List<String> skills;           
    private Map<String, BigDecimal> salary; 
	//... 

输出

 {
  "name" : "mkyong",
  "age" : 38
} 

3.@ JSON include–字段级别

Staff.java

 import com.fasterxml.jackson.annotation.JsonInclude;

public class Staff {

    private String name;
    private int age;

	@JsonInclude(JsonInclude.Include.NON_NULL) //ignore null field on this property only
    private String[] position;              

	@JsonInclude(JsonInclude.Include.NON_NULL) //ignore null field on this property only
    private List<String> skills;           

    private Map<String, BigDecimal> salary; 

输出

 {
  "name" : "mkyong",
  "age" : 38,
  "salary" : null
} 

4.object mapper . setserializationinclusion

或者,我们也可以配置全局忽略空字段:

JacksonExample2.java

 package com.mkyong;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;

public class JacksonExample2 {

    public static void main(String[] args) {

        ObjectMapper mapper = new ObjectMapper();

        Staff staff = new Staff("mkyong", 38);

        try {

            // ignore the null fields globally
            mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

            String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(staff);

            System.out.println(json);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

} 

输出

 {
  "name" : "mkyong",
  "age" : 38
} 

参考

Tags : jackson json null

杰克逊——如何解析 JSON

原文:http://web.archive.org/web/20230101150211/https://www.mkyong.com/java/jackson-how-to-parse-json/

Jackson 提供writeValue()readValue()方法将 Java 对象与 JSON 相互转换。

mapper.writeValue–Java 对象到 JSON

 ObjectMapper mapper = new ObjectMapper();

	// Java object to JSON file
	mapper.writeValue(new File("c:\\test\\staff.json"), new Staff());

	// Java object to JSON string, default compact-print
	String jsonString = mapper.writeValueAsString(new Staff());

	// pretty-print
	String jsonString2 = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(new Staff()); 

mapper.readValue–JSON 到 Java 对象

 ObjectMapper mapper = new ObjectMapper();

	//JSON file to Java object
	Staff obj = mapper.readValue(new File("c:\\test\\staff.json"), Staff.class);

	//JSON URL to Java object
	Staff obj = mapper.readValue(new URL("http://some-domains/api/staff.json"), Staff.class);

	//JSON string to Java Object
	Staff obj = mapper.readValue("{'name' : 'mkyong'}", Staff.class); 

用杰克逊 2.9.8 测试的 PS

1.下载杰克逊

声明jackson-databind,它将拉入jackson-annotationsjackson-core

pom.xml

 <dependency>
		<groupId>com.fasterxml.jackson.core</groupId>
		<artifactId>jackson-databind</artifactId>
		<version>2.9.8</version>
	</dependency> 

Terminal

 $ mvn dependency:tree

\- com.fasterxml.jackson.core:jackson-databind:jar:2.9.8:compile
[INFO]    +- com.fasterxml.jackson.core:jackson-annotations:jar:2.9.0:compile
[INFO]    \- com.fasterxml.jackson.core:jackson-core:jar:2.9.8:compile 

2.波乔

一个简单的 Java 对象 POJO,用于以后的测试。

Staff.java

 public class Staff {

    private String name;
    private int age;
    private String[] position;              //  Array
    private List<String> skills;            //  List
    private Map<String, BigDecimal> salary; //  Map

	// getters , setters, some boring stuff
} 

3.JSON 的 Java 对象

JacksonExample1.java

 package com.mkyong;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class JacksonExample1 {

    public static void main(String[] args) {

        ObjectMapper mapper = new ObjectMapper();

        Staff staff = createStaff();

        try {

            // Java objects to JSON file
            mapper.writeValue(new File("c:\\test\\staff.json"), staff);

            // Java objects to JSON string - compact-print
            String jsonString = mapper.writeValueAsString(staff);

            System.out.println(jsonString);

            // Java objects to JSON string - pretty-print
            String jsonInString2 = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(staff);

            System.out.println(jsonInString2);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private static Staff createStaff() {

        Staff staff = new Staff();

        staff.setName("mkyong");
        staff.setAge(38);
        staff.setPosition(new String[]{"Founder", "CTO", "Writer"});
        Map<String, BigDecimal> salary = new HashMap() {{
            put("2010", new BigDecimal(10000));
            put("2012", new BigDecimal(12000));
            put("2018", new BigDecimal(14000));
        }};
        staff.setSalary(salary);
        staff.setSkills(Arrays.asList("java", "python", "node", "kotlin"));

        return staff;

    }

} 

输出

c:\test\staff.json

 {"name":"mkyong","age":38,"position":["Founder","CTO","Writer"],"skills":["java","python","node","kotlin"],"salary":{"2018":14000,"2012":12000,"2010":10000}} 

Terminal

 {"name":"mkyong","age":38,"position":["Founder","CTO","Writer"],"skills":["java","python","node","kotlin"],"salary":{"2018":14000,"2012":12000,"2010":10000}}

{
  "name" : "mkyong",
  "age" : 38,
  "position" : [ "Founder", "CTO", "Writer" ],
  "skills" : [ "java", "python", "node", "kotlin" ],
  "salary" : {
    "2018" : 14000,
    "2012" : 12000,
    "2010" : 10000
  }
} 

4.JSON 到 Java 对象

JacksonExample2.java

 package com.mkyong;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.io.IOException;

public class JacksonExample2 {

    public static void main(String[] args) {

        ObjectMapper mapper = new ObjectMapper();

        try {

            // JSON file to Java object
            Staff staff = mapper.readValue(new File("c:\\test\\staff.json"), Staff.class);

            // JSON string to Java object
            String jsonInString = "{\"name\":\"mkyong\",\"age\":37,\"skills\":[\"java\",\"python\"]}";
            Staff staff2 = mapper.readValue(jsonInString, Staff.class);

            // compact print
            System.out.println(staff2);

            // pretty print
            String prettyStaff1 = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(staff2);

            System.out.println(prettyStaff1);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

} 

输出

 Staff{name='mkyong', age=37, position=null, skills=[java, python], salary=null}

{
  "name" : "mkyong",
  "age" : 37,
  "position" : null,
  "skills" : [ "java", "python" ],
  "salary" : null
} 

5.@ JSON property–JSON 字段命名

5.1 违约

 public class Staff {

    private String name;
	private int age; 

输出

 {"name":"abc", "age":38} 

5.2 用@JsonProperty更改属性名称

 public class Staff {

    @JsonProperty("custom_name")
    private String name;
	private int age; 

输出

 {"custom_name":"abc", "age":38} 

6.@ JSON include–忽略空字段

默认情况下,Jackson 将包含null字段。

 {
  "name" : "mkyong",
  "age" : 38,
  "position" : null,
  "skills" : null,
  "salary" : null
} 

6.1 @JsonInclude类级别。

Staff.java

 import com.fasterxml.jackson.annotation.JsonInclude;

											//	ignore null fields , class level
@JsonInclude(JsonInclude.Include.NON_NULL) 	//  ignore all null fields
public class Staff {

    private String name;
    private int age;
    private String[] position;              
    private List<String> skills;           
    private Map<String, BigDecimal> salary; 
	//... 

6.2 字段级上的@JsonInclude

Staff.java

 import com.fasterxml.jackson.annotation.JsonInclude;

public class Staff {

    private String name;
    private int age;

	@JsonInclude(JsonInclude.Include.NON_NULL) //ignore null field on this property only
    private String[] position;              

    private List<String> skills;           

    private Map<String, BigDecimal> salary; 

输出

 {
  "name" : "mkyong",
  "age" : 38,
  "skill" : null,
  "salary" : null
} 

6.3 全球。

 ObjectMapper mapper = new ObjectMapper();

	// ignore all null fields globally
	mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 

Note
More examples for How to ignore null fields with Jackson

7.@JsonView

7.1@JsonView用于限制不同用户显示的字段。例如:

CompanyViews.java

 package com.mkyong;

public class CompanyViews {

    public static class Normal{};

    public static class Manager extends Normal{};

} 

普通视图仅显示姓名和年龄,经理视图可以显示所有信息。

Staff.java

 import com.fasterxml.jackson.annotation.JsonView;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class Staff {

    @JsonView(CompanyViews.Normal.class)
    private String name;

    @JsonView(CompanyViews.Normal.class)
    private int age;

    @JsonView(CompanyViews.Manager.class)
    private String[] position;

    @JsonView(CompanyViews.Manager.class)
    private List<String> skills;

    @JsonView(CompanyViews.Manager.class)
    private Map<String, BigDecimal> salary; 

JacksonExample.java

 package com.mkyong;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class JacksonExample {

    public static void main(String[] args) {

        ObjectMapper mapper = new ObjectMapper();

        Staff staff = createStaff();

        try {

            // to enable pretty print
            mapper.enable(SerializationFeature.INDENT_OUTPUT);

            // normal
            String normalView = mapper
				.writerWithView(CompanyViews.Normal.class)
				.writeValueAsString(staff);

            System.out.format("Normal views\n%s\n", normalView);

            // manager
            String managerView = mapper
				.writerWithView(CompanyViews.Manager.class)
				.writeValueAsString(staff);

            System.out.format("Manager views\n%s\n", managerView);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private static Staff createStaff() {

        Staff staff = new Staff();

        staff.setName("mkyong");
        staff.setAge(38);
        staff.setPosition(new String[]{"Founder", "CTO", "Writer"});
        Map<String, BigDecimal> salary = new HashMap() {{
            put("2010", new BigDecimal(10000));
            put("2012", new BigDecimal(12000));
            put("2018", new BigDecimal(14000));
        }};
        staff.setSalary(salary);
        staff.setSkills(Arrays.asList("java", "python", "node", "kotlin"));

        return staff;

    }

} 

输出

 Normal views
{
  "name" : "mkyong",
  "age" : 38
}

Manager views
{
  "name" : "mkyong",
  "age" : 38,
  "position" : [ "Founder", "CTO", "Writer" ],
  "skills" : [ "java", "python", "node", "kotlin" ],
  "salary" : {
    "2018" : 14000,
    "2012" : 12000,
    "2010" : 10000
  }
} 

Note
Read this Jackson @JsonView example

8.@JsonIgnore 和@JsonIgnoreProperties

默认情况下,Jackson 包括所有字段,甚至包括statictransient字段。

8.1 @JsonIgnore忽略字段级的字段。

 import com.fasterxml.jackson.annotation.JsonIgnore;

public class Staff {

    private String name;
    private int age;
    private String[] position;

    @JsonIgnore
    private List<String> skills;

    @JsonIgnore
    private Map<String, BigDecimal> salary; 

输出

 {
  "name" : "mkyong",
  "age" : 38,
  "position" : [ "Founder", "CTO", "Writer" ]
} 

8.2 @JsonIgnoreProperties忽略类级别的字段。

 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties({"salary", "position"})
public class Staff {

    private String name;
    private int age;
    private String[] position;
    private List<String> skills;
    private Map<String, BigDecimal> salary; 

输出

 {
  "name" : "mkyong",
  "age" : 38,
  "skills" : [ "java", "python", "node", "kotlin" ]
} 

9.常见问题

9.1 将 JSON 数组字符串转换为列表

 String json = "[{\"name\":\"mkyong\", \"age\":38}, {\"name\":\"laplap\", \"age\":5}]";

	List<Staff> list = Arrays.asList(mapper.readValue(json, Staff[].class));

	// or like this:
	// List<Staff> list = mapper.readValue(json, new TypeReference<List<Staff>>(){}); 

9.2 将 JSON 字符串转换为映射

 String json = "{\"name\":\"mkyong\", \"age\":\"33\"}";

	Map<String, String> map = mapper.readValue(json, Map.class);

	// or like this:
	//Map<String, String> map = mapper.readValue(json, new TypeReference<Map<String, String>>(){});

	map.forEach((k, v) -> System.out.format("[key]:%s \t[value]:%s\n", k, v)); 

输出

 [key]:name 	[value]:mkyong
[key]:age 	[value]:33 

9.3 如果某个复杂的 JSON 结构不容易映射到 Java 类怎么办?
回答:试试 Jackson TreeModel 把 JSON 数据转换成JsonNode,这样我们就可以很方便的添加、更新或者删除 JSON 节点。

参考

Jackson @JsonView 示例

原文:http://web.archive.org/web/20230101150211/https://www.mkyong.com/java/jackson-jsonview-examples/

在 Jackson 中,我们可以使用@JsonView来限制或控制不同用户的字段显示。

用于测试的 POJO。

Staff.java

 package com.mkyong;

public class Staff {

    private String name;
    private int age;
    private String[] position;
    private List<String> skills;
    private Map<String, BigDecimal> salary;

	// getters , setters , boring stuff
} 

用杰克逊 2.9.8 测试的 PS

1.视图

一个标准的 Java 类来定义 3 个视图:普通视图、经理视图和人力资源视图。

CompanyViews.java

 package com.mkyong;

public class CompanyViews {

    public static class Normal{};

    public static class Manager extends Normal{};

    public static class HR extends Normal{};

} 

2.Json 视图

@JsonView置于字段级别,以限制不同视图的字段显示。

  • 正常–显示姓名和年龄。
  • 经理-显示姓名、年龄、职位和技能
  • HR–显示姓名、年龄、工资和职位

P.S .经理无权查看薪资字段,HR 不关心你有什么技能🙂

Staff.java

 package com.mkyong;

import com.fasterxml.jackson.annotation.JsonView;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class Staff {

    @JsonView(CompanyViews.Normal.class)
    private String name;

    @JsonView(CompanyViews.Normal.class)
    private int age;

    // two views
    @JsonView({CompanyViews.HR.class, CompanyViews.Manager.class})
    private String[] position;

    @JsonView(CompanyViews.Manager.class)
    private List<String> skills;

    @JsonView(CompanyViews.HR.class)
    private Map<String, BigDecimal> salary; 

3.Jackson–启用@JsonView

3.1 下面的例子向您展示了如何使用mapper.writerWithView()来启用JsonView

JacksonExample.java

 package com.mkyong;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class JacksonExample {

    public static void main(String[] args) {

        ObjectMapper mapper = new ObjectMapper();

        Staff staff = createStaff();

        try {

            // to enable pretty print
            mapper.enable(SerializationFeature.INDENT_OUTPUT);

            // normal
            String normalView = mapper.writerWithView(CompanyViews.Normal.class).writeValueAsString(staff);

            System.out.format("Normal views\n%s\n", normalView);

            // manager
            String managerView = mapper.writerWithView(CompanyViews.Manager.class).writeValueAsString(staff);

            System.out.format("Manager views\n%s\n", managerView);

            // hr
            String hrView = mapper.writerWithView(CompanyViews.HR.class).writeValueAsString(staff);

            System.out.format("HR views\n%s\n", hrView);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private static Staff createStaff() {

        Staff staff = new Staff();

        staff.setName("mkyong");
        staff.setAge(38);
        staff.setPosition(new String[]{"Founder", "CTO", "Writer"});
        Map<String, BigDecimal> salary = new HashMap() {{
            put("2010", new BigDecimal(10000));
            put("2012", new BigDecimal(12000));
            put("2018", new BigDecimal(14000));
        }};
        staff.setSalary(salary);
        staff.setSkills(Arrays.asList("java", "python", "node", "kotlin"));

        return staff;

    }

} 

输出

 Normal views
{
  "name" : "mkyong",
  "age" : 38
}

Manager views
{
  "name" : "mkyong",
  "age" : 38,
  "position" : [ "Founder", "CTO", "Writer" ],
  "skills" : [ "java", "python", "node", "kotlin" ]
}

HR views
{
  "name" : "mkyong",
  "age" : 38,
  "position" : [ "Founder", "CTO", "Writer" ],
  "salary" : {
    "2018" : 14000,
    "2012" : 12000,
    "2010" : 10000
  }
} 

参考

Tags : jackson json

Jackson–流模型示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/tutorials/java-json-tutorials/url=https://www.mkyong.com/java/jackson-streaming-api-to-read-and-write-json/

这个 Jackson 教程向你展示了如何使用JsonGenerator将 JSON 字符串和 JSON 数组写入一个文件,并使用JsonParser读取它

杰克逊流式 API

  • JsonGenerator–编写 JSON
  • JsonParser –解析 JSON

Note
The Jackson streaming mode is the underlying processing model that data-binding and Tree Model both build upon. It is the best performance and control over the JSON parsing and JSON generation.

用杰克逊 2.9.8 测试

1.JSON generator–编写 JSON

1.1 将 JSON 写入文件。

JacksonExample1.java

 package com.mkyong;

import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.io.IOException;

public class JacksonExample1 {

    public static void main(String[] args) {

        ObjectMapper mapper = new ObjectMapper();

        try (JsonGenerator jGenerator =
                     mapper.getFactory().createGenerator(
                             new File("c:\\projects\\user.json")
                             , JsonEncoding.UTF8)) {

            jGenerator.writeStartObject();                                  // {

            jGenerator.writeStringField("name", "mkyong");  				// "name" : "mkyong"
            jGenerator.writeNumberField("age", 38);         				// "age" : 38

            jGenerator.writeFieldName("messages");                          // "messages" :

            jGenerator.writeStartArray();                                   // [

            jGenerator.writeString("msg 1");                            		// "msg 1"
            jGenerator.writeString("msg 2");                            		// "msg 2"
            jGenerator.writeString("msg 3");                            		// "msg 3"

            jGenerator.writeEndArray();                                     // ]

            jGenerator.writeEndObject();                                    // }

        } catch (JsonGenerationException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
} 

输出

c:\projects\user.json

 {"name":"mkyong","age":38,"messages":["msg 1","msg 2","msg 3"]} 

2.JSON generator–编写 JSON 数组

2.1 1.1 将 JSON 数组写入文件。

JacksonExample2.java

 package com.mkyong;

import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.io.IOException;

public class JacksonExample2 {

    public static void main(String[] args) {

        ObjectMapper mapper = new ObjectMapper();

        try (JsonGenerator jGenerator =
                     mapper.getFactory().createGenerator(
                             new File("c:\\projects\\user2.json")
                             , JsonEncoding.UTF8)) {

            // pretty print
            jGenerator.useDefaultPrettyPrinter();

            // start array
            jGenerator.writeStartArray();                                   // [

            jGenerator.writeStartObject();                                  // {

            jGenerator.writeStringField("name", "mkyong");  				// "name" : "mkyong"
            jGenerator.writeNumberField("age", 38);         				// "age" : 38

            jGenerator.writeFieldName("messages");                          // "messages" :

            jGenerator.writeStartArray();                                   // [

            jGenerator.writeString("msg 1");                            	// "msg 1"
            jGenerator.writeString("msg 2");                            	// "msg 2"
            jGenerator.writeString("msg 3");                            	// "msg 3"

            jGenerator.writeEndArray();                                     // ]

            jGenerator.writeEndObject();                                    // }

            // next object, pls

            jGenerator.writeStartObject();                                  // {

            jGenerator.writeStringField("name", "lap");  					// "name" : "lap"
            jGenerator.writeNumberField("age", 5);         					// "age" : 5

            jGenerator.writeFieldName("messages");                          // "messages" :

            jGenerator.writeStartArray();                                   // [

            jGenerator.writeString("msg a");                            	// "msg a"
            jGenerator.writeString("msg b");                            	// "msg b"
            jGenerator.writeString("msg c");                            	// "msg c"

            jGenerator.writeEndArray();                                     // ]

            jGenerator.writeEndObject();                                    // }

            jGenerator.writeEndArray();                                     // ]

        } catch (JsonGenerationException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
} 

输出

c:\projects\user2.json

 [ 
	{
	  "name" : "mkyong",
	  "age" : 38,
	  "messages" : [ "msg 1", "msg 2", "msg 3" ]
	}, {
	  "name" : "lap",
	  "age" : 5,
	  "messages" : [ "msg a", "msg b", "msg c" ]
	} 
] 

3.JSON parser–读取 JSON

令牌
在 Jackson streaming 模式下,它将 JSON 字符串拆分成一个令牌列表,每个令牌都会被增量处理。举个例子,

 {
   "name":"mkyong"
} 
  • 令牌 1 = {
  • 令牌 2 =名称
  • 令牌 3 = mkyong
  • 令牌 4 = }

3.1 JsonParser解析 JSON 文件的示例。

c:\projects\user.json

 {"name":"mkyong","age":38,"messages":["msg 1","msg 2","msg 3"]} 

JacksonExample3.java

 package com.mkyong;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.JsonMappingException;

import java.io.File;
import java.io.IOException;

public class JacksonExample3 {

    public static void main(String[] args) {

        try (JsonParser jParser = new JsonFactory()
				.createParser(new File("c:\\projects\\user.json"));) {

            // loop until token equal to "}"
            while (jParser.nextToken() != JsonToken.END_OBJECT) {

                String fieldname = jParser.getCurrentName();

                if ("name".equals(fieldname)) {
                    // current token is "name",
                    // move to next, which is "name"'s value
                    jParser.nextToken();
                    System.out.println(jParser.getText());
                }

                if ("age".equals(fieldname)) {
                    jParser.nextToken();
                    System.out.println(jParser.getIntValue());
                }

                if ("messages".equals(fieldname)) {

                    if (jParser.nextToken() == JsonToken.START_ARRAY) {
                        // messages is array, loop until token equal to "]"
                        while (jParser.nextToken() != JsonToken.END_ARRAY) {
                            System.out.println(jParser.getText());
                        }
                    }

                }

            }

        } catch (JsonGenerationException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

} 

输出

 mkyong
38
msg 1
msg 2
msg 3 

4.JSON parser–读取 JSON 数组

4.1 JsonParser解析 JSON 数组文件的例子。

c:\projects\user2.json

 [ 
	{
	  "name" : "mkyong",
	  "age" : 38,
	  "messages" : [ "msg 1", "msg 2", "msg 3" ]
	}, {
	  "name" : "lap",
	  "age" : 5,
	  "messages" : [ "msg a", "msg b", "msg c" ]
	} 
] 

JacksonExample4.java

 package com.mkyong;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.JsonMappingException;

import java.io.File;
import java.io.IOException;

public class JacksonExample4 {

    public static void main(String[] args) {

        try (JsonParser jParser = new JsonFactory()
                .createParser(new File("c:\\projects\\user2.json"));) {

            // JSON array?
            if (jParser.nextToken() == JsonToken.START_ARRAY) {

                while (jParser.nextToken() != JsonToken.END_ARRAY) {

                    // loop until token equal to "}"
                    while (jParser.nextToken() != JsonToken.END_OBJECT) {

                        String fieldname = jParser.getCurrentName();
                        if ("name".equals(fieldname)) {
                            // current token is "name",
                            // move to next, which is "name"'s value
                            jParser.nextToken();
                            System.out.println(jParser.getText());
                        }

                        if ("age".equals(fieldname)) {
                            jParser.nextToken();
                            System.out.println(jParser.getIntValue());
                        }

                        if ("messages".equals(fieldname)) {

                            //jParser.nextToken(); // current token is "[", move next
                            if (jParser.nextToken() == JsonToken.START_ARRAY) {
                                // messages is array, loop until token equal to "]"
                                while (jParser.nextToken() != JsonToken.END_ARRAY) {
                                    System.out.println(jParser.getText());
                                }
                            }

                        }

                    }

                }
            }

        } catch (JsonGenerationException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

} 

输出

 mkyong
38
msg 1
msg 2
msg 3
lap
5
msg a
msg b
msg c 

Note
More Jackson examples

参考

杰克逊树模型示例

原文:http://web.archive.org/web/20230101150211/https://www.mkyong.com/java/jackson-tree-model-example/

在 Jackson 中,我们可以使用Tree Model来表示 JSON 结构,并通过JsonNode执行 CRUD 操作,类似于 XML DOM 树。这个杰克逊Tree Model非常有用,尤其是在 JSON 结构不能很好地映射到 Java 类的情况下。

pom.xml

 <dependency>
		<groupId>com.fasterxml.jackson.core</groupId>
		<artifactId>jackson-databind</artifactId>
		<version>2.9.8</version>
	</dependency> 

用杰克逊 2.9.8 测试的 PS

1.遍历 JSON

1.1 Jackson TreeModel遍历以下 JSON 文件的示例:

C:\projects\user.json

 {
  "id": 1,
  "name": {
    "first": "Yong",
    "last": "Mook Kim"
  },
  "contact": [
    {
      "type": "phone/home",
      "ref": "111-111-1234"
    },
    {
      "type": "phone/work",
      "ref": "222-222-2222"
    }
  ]
} 

1.2 逐个处理JsonNode

JacksonTreeModelExample1.java

 package com.mkyong;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.io.IOException;

public class JacksonTreeModelExample1 {

    private static final ObjectMapper mapper = new ObjectMapper();

    public static void main(String[] args) {

        try {

            JsonNode root = mapper.readTree(new File("c:\\projects\\user.json"));

            // Get id
            long id = root.path("id").asLong();
            System.out.println("id : " + id);

            // Get Name
            JsonNode nameNode = root.path("name");
            if (!nameNode.isMissingNode()) {        // if "name" node is exist
                System.out.println("firstName : " + nameNode.path("first").asText());
                System.out.println("middleName : " + nameNode.path("middle").asText());
                System.out.println("lastName : " + nameNode.path("last").asText());
            }

            // Get Contact
            JsonNode contactNode = root.path("contact");
            if (contactNode.isArray()) {

                System.out.println("Is this node an Array? " + contactNode.isArray());

                for (JsonNode node : contactNode) {
                    String type = node.path("type").asText();
                    String ref = node.path("ref").asText();
                    System.out.println("type : " + type);
                    System.out.println("ref : " + ref);

                }
            }

        } catch (JsonGenerationException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

} 

输出

 id : 1

firstName : Yong
middleName : 
lastName : Mook Kim

Is this node an Array? true
type : phone/home
ref : 111-111-1234
type : phone/work
ref : 222-222-2222 

2.遍历 JSON 数组

2.1 JSON 文件,顶层代表一个数组。

c:\projects\user2.json

 [
  {
    "id": 1,
    "name": {
      "first": "Yong",
      "last": "Mook Kim"
    },
    "contact": [
      {
        "type": "phone/home",
        "ref": "111-111-1234"
      },
      {
        "type": "phone/work",
        "ref": "222-222-2222"
      }
    ]
  },
  {
    "id": 2,
    "name": {
      "first": "Yong",
      "last": "Zi Lap"
    },
    "contact": [
      {
        "type": "phone/home",
        "ref": "333-333-1234"
      },
      {
        "type": "phone/work",
        "ref": "444-444-4444"
      }
    ]
  }
] 

2.2 概念是一样的,只是循环 JSON 数组:

 JsonNode rootArray = mapper.readTree(new File("c:\\projects\\user2.json"));

	for (JsonNode root : rootArray) {
		// get node like the above example 1
	} 

JacksonTreeModelExample2.java

 package com.mkyong;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.io.IOException;

public class JacksonTreeModelExample2 {

    private static final ObjectMapper mapper = new ObjectMapper();

    public static void main(String[] args) {

        try {

            JsonNode rootArray = mapper.readTree(new File("c:\\projects\\user2.json"));

            for (JsonNode root : rootArray) {

                // Get id
                long id = root.path("id").asLong();
                System.out.println("id : " + id);

                // Get Name
                JsonNode nameNode = root.path("name");
                if (!nameNode.isMissingNode()) {        // if "name" node is exist
                    System.out.println("firstName : " + nameNode.path("first").asText());
                    System.out.println("middleName : " + nameNode.path("middle").asText());
                    System.out.println("lastName : " + nameNode.path("last").asText());
                }

                // Get Contact
                JsonNode contactNode = root.path("contact");
                if (contactNode.isArray()) {

                    System.out.println("Is this node an Array? " + contactNode.isArray());

                    for (JsonNode node : contactNode) {
                        String type = node.path("type").asText();
                        String ref = node.path("ref").asText();
                        System.out.println("type : " + type);
                        System.out.println("ref : " + ref);

                    }
                }

            }

        } catch (JsonGenerationException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

} 

输出

 id : 1
firstName : Yong
middleName : 
lastName : Mook Kim
Is this node an Array? true
type : phone/home
ref : 111-111-1234
type : phone/work
ref : 222-222-2222

id : 2
firstName : Yong
middleName : 
lastName : Zi Lap
Is this node an Array? true
type : phone/home
ref : 333-333-1234
type : phone/work
ref : 444-444-4444 

3.树形模型 CRUD 示例

3.1 这个例子,向你展示了如何创建、更新和删除 JSON 节点,要修改 JSON 节点,我们需要将其转换为ObjectNode。阅读评论,不言自明。

JacksonTreeModelExample3.java

 package com.mkyong;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

import java.io.File;
import java.io.IOException;

public class JacksonTreeModelExample3 {

    private static final ObjectMapper mapper = new ObjectMapper();

    public static void main(String[] args) {

        try {

            JsonNode root = mapper.readTree(new File("c:\\projects\\user.json"));

            String resultOriginal = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(root);
            System.out.println("Before Update " + resultOriginal);

            // 1\. Update id to 1000
            ((ObjectNode) root).put("id", 1000L);

            // 2\. If middle name is empty , update to M
            ObjectNode nameNode = (ObjectNode) root.path("name");
            if ("".equals(nameNode.path("middle").asText())) {
                nameNode.put("middle", "M");
            }

            // 3\. Create a new field in nameNode
            nameNode.put("nickname", "mkyong");

            // 4\. Remove last field in nameNode
            nameNode.remove("last");

            // 5\. Create a new ObjectNode and add to root
            ObjectNode positionNode = mapper.createObjectNode();
            positionNode.put("name", "Developer");
            positionNode.put("years", 10);
            ((ObjectNode) root).set("position", positionNode);

            // 6\. Create a new ArrayNode and add to root
            ArrayNode gamesNode = mapper.createArrayNode();

            ObjectNode game1 = mapper.createObjectNode().objectNode();
            game1.put("name", "Fall Out 4");
            game1.put("price", 49.9);

            ObjectNode game2 = mapper.createObjectNode().objectNode();
            game2.put("name", "Dark Soul 3");
            game2.put("price", 59.9);

            gamesNode.add(game1);
            gamesNode.add(game2);
            ((ObjectNode) root).set("games", gamesNode);

            // 7\. Append a new Node to ArrayNode
            ObjectNode email = mapper.createObjectNode();
            email.put("type", "email");
            email.put("ref", "abc@mkyong.com");

            JsonNode contactNode = root.path("contact");
            ((ArrayNode) contactNode).add(email);

            String resultUpdate = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(root);

            System.out.println("After Update " + resultUpdate);

        } catch (JsonGenerationException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

} 

输出

 Before Update {
  "id" : 1,
  "name" : {
    "first" : "Yong",
    "last" : "Mook Kim"
  },
  "contact" : [ {
    "type" : "phone/home",
    "ref" : "111-111-1234"
  }, {
    "type" : "phone/work",
    "ref" : "222-222-2222"
  } ]
}

After Update {
  "id" : 1000,
  "name" : {
    "first" : "Yong",
    "middle" : "M",
    "nickname" : "mkyong"
  },
  "contact" : [ {
    "type" : "phone/home",
    "ref" : "111-111-1234"
  }, {
    "type" : "phone/work",
    "ref" : "222-222-2222"
  }, {
    "type" : "email",
    "ref" : "abc@mkyong.com"
  } ],
  "position" : {
    "name" : "Developer",
    "years" : 10
  },
  "games" : [ {
    "name" : "Fall Out 4",
    "price" : 49.9
  }, {
    "name" : "Dark Soul 3",
    "price" : 59.9
  } ]
} 

参考

Java 8 双消费示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-biconsumer-examples/

在 Java 8 中, BiConsumer 是一个函数接口;它接受两个参数,不返回任何内容。

 @FunctionalInterface
public interface BiConsumer<T, U> {
  void accept(T t, U u);
} 

延伸阅读Java 8 消费者实例

1.双消费者

JavaBiConsumer1.java

 package com.mkyong.java8;

import java.util.function.Consumer;

public class JavaBiConsumer1 {

    public static void main(String[] args) {

      BiConsumer<Integer, Integer> addTwo = (x, y) -> System.out.println(x + y);
      addTwo.accept(1, 2);    // 3

    }

} 

输出

 3 

2.高阶函数

2.1 这个例子接受BiConsumer作为参数,创建一个泛型addTwo来连接两个对象。

JavaBiConsumer2.java

 package com.mkyong.java8;

import java.util.function.BiConsumer;

public class JavaBiConsumer2 {

    public static void main(String[] args) {

        addTwo(1, 2, (x, y) -> System.out.println(x + y));          // 3
        addTwo("Node", ".js", (x, y) -> System.out.println(x + y)); // Node.js

    }

    static <T> void addTwo(T a1, T a2, BiConsumer<T, T> c) {
        c.accept(a1, a2);
    }

} 

输出

 3
Node.js 

2.2 更多BiConsumer例子。

JavaBiConsumer3.java

 package com.mkyong.java8;

import java.util.function.BiConsumer;

public class JavaBiConsumer3 {

    public static void main(String[] args) {

        math(1, 1, (x, y) -> System.out.println(x + y));   // 2
        math(1, 1, (x, y) -> System.out.println(x - y));   // 0
        math(1, 1, (x, y) -> System.out.println(x * y));   // 1
        math(1, 1, (x, y) -> System.out.println(x / y));   // 1

    }

    static <Integer> void math(Integer a1, Integer a2, BiConsumer<Integer, Integer> c) {
        c.accept(a1, a2);
    }

} 

输出

 2
0
1
1 

3.Map.forEach

在 JDK 源代码中,Map.forEach接受一个BiConsumer作为参数。

Map.java

 default void forEach(BiConsumer<? super K, ? super V> action) {
        Objects.requireNonNull(action);
        for (Map.Entry<K, V> entry : entrySet()) {
            K k;
            V v;
            try {
                k = entry.getKey();
                v = entry.getValue();
            } catch (IllegalStateException ise) {
                // this usually means the entry is no longer in the map.
                throw new ConcurrentModificationException(ise);
            }
            action.accept(k, v);
        }
    } 

JavaMapBiConsumer.java

 package com.mkyong.java8;

import java.util.LinkedHashMap;
import java.util.Map;

public class JavaMapBiConsumer {

    public static void main(String[] args) {

        Map<Integer, String> map = new LinkedHashMap<>();

        map.put(1, "Java");
        map.put(2, "C++");
        map.put(3, "Rust");
        map.put(4, "JavaScript");
        map.put(5, "Go");

        map.forEach((k, v) -> System.out.println(k + ":" + v));

    }

} 

输出

 1:Java
2:C++
3:Rust
4:JavaScript
5:Go 

参考

Java 8 双功能示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-bifunction-examples/

在 Java 8 中, BiFunction 是一个函数接口;它接受两个参数并返回一个对象。

BiFunction.java

 @FunctionalInterface
public interface BiFunction<T, U, R> {

      R apply(T t, U u);

} 
  • t–函数第一个参数的类型。
  • u–函数的第二个参数的类型。
  • r–函数结果的类型。

1.BiFunction<Integer, Integer, Integer>

1.1 本例采用两个Integers并返回一个IntegerDoubleList

Java8BiFunction1.java

 package com.mkyong;

import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;

public class Java8BiFunction1 {

    public static void main(String[] args) {

        // takes two Integers and return an Integer
        BiFunction<Integer, Integer, Integer> func = (x1, x2) -> x1 + x2;

        Integer result = func.apply(2, 3);

        System.out.println(result); // 5

        // take two Integers and return an Double
        BiFunction<Integer, Integer, Double> func2 = (x1, x2) -> Math.pow(x1, x2);

        Double result2 = func2.apply(2, 4);

        System.out.println(result2);    // 16.0

        // take two Integers and return a List<Integer>
        BiFunction<Integer, Integer, List<Integer>> func3 = (x1, x2) -> Arrays.asList(x1 + x2);

        List<Integer> result3 = func3.apply(2, 3);

        System.out.println(result3);

    }

} 

输出

 5
16.0
[5] 

2.BiFunction<Integer, Integer, Double>

2.1 这个BiFunction取两个Integer返回一个Double,用andThen()用一个Function把它链接起来,把Double转换成String

Java8BiFunction2a.java

 package com.mkyong;

import java.util.function.BiFunction;
import java.util.function.Function;

public class Java8BiFunction2a {

    public static void main(String[] args) {

        // Math.pow(a1, a2) returns Double
        BiFunction<Integer, Integer, Double> func1 = (a1, a2) -> Math.pow(a1, a2);

        // takes Double, returns String
        Function<Double, String> func2 = (input) -> "Result : " + String.valueOf(input);

        String result = func1.andThen(func2).apply(2, 4);

        System.out.println(result);

    }

} 

输出

 Result : 16.0 

2.2 这个例子将上面的程序转换成一个方法,该方法接受BiFunctionFunction作为参数,并将它们链接在一起。

Java8BiFunction2b.java

 package com.mkyong;

import java.util.function.BiFunction;
import java.util.function.Function;

public class Java8BiFunction2b {

    public static void main(String[] args) {

        String result = powToString(2, 4,
                (a1, a2) -> Math.pow(a1, a2),
                (r) -> "Result : " + String.valueOf(r));

        System.out.println(result); // Result : 16.0

    }

    public static <R> R powToString(Integer a1, Integer a2,
                                    BiFunction<Integer, Integer, Double> func,
                                    Function<Double, R> func2) {

        return func.andThen(func2).apply(a1, a2);

    }

} 

输出

 Result : 16.0 

2.3 此示例将上述方法转换为泛型方法:

 public static <A1, A2, R1, R2> R2 convert(A1 a1, A2 a2,
                                          BiFunction<A1, A2, R1> func,
                                          Function<R1, R2> func2) {

    return func.andThen(func2).apply(a1, a2);

} 

这个泛型方法有很多可能性,让我们看看:

Java8BiFunction2c.java

 package com.mkyong;

import java.util.function.BiFunction;
import java.util.function.Function;

public class Java8BiFunction2c {

    public static void main(String[] args) {

        // Take two Integers, pow it into a Double, convert Double into a String.
        String result = convert(2, 4,
                (a1, a2) -> Math.pow(a1, a2),
                (r) -> "Pow : " + String.valueOf(r));

        System.out.println(result);     // Pow : 16.0

        // Take two Integers, multiply into an Integer, convert Integer into a String.
        String result2 = convert(2, 4,
                (a1, a2) -> a1 * a1,
                (r) -> "Multiply : " + String.valueOf(r));

        System.out.println(result2);    // Multiply : 4

        // Take two Strings, join both, join "cde"
        String result3 = convert("a", "b",
                (a1, a2) -> a1 + a2,
                (r) -> r + "cde");      // abcde

        System.out.println(result3);

        // Take two Strings, join both, convert it into an Integer
        Integer result4 = convert("100", "200",
                (a1, a2) -> a1 + a2,
                (r) -> Integer.valueOf(r));

        System.out.println(result4);    // 100200

    }

    public static <A1, A2, R1, R2> R2 convert(A1 a1, A2 a2,
                                              BiFunction<A1, A2, R1> func,
                                              Function<R1, R2> func2) {

        return func.andThen(func2).apply(a1, a2);

    }

} 

输出

 Pow : 16.0
Multiply : 4
abcde
100200 

3.工厂

3.1 这个例子使用BiFunction创建一个对象,充当一个工厂模式。

Java8BiFunction3.java

 package com.mkyong;

import java.util.function.BiFunction;

public class Java8BiFunction3 {

    public static void main(String[] args) {

        GPS obj = factory("40.741895", "-73.989308", GPS::new);
        System.out.println(obj);

    }

    public static <R extends GPS> R factory(String Latitude, String Longitude,
                                            BiFunction<String, String, R> func) {
        return func.apply(Latitude, Longitude);
    }

}

class GPS {

    String Latitude;
    String Longitude;

    public GPS(String latitude, String longitude) {
        Latitude = latitude;
        Longitude = longitude;
    }

    public String getLatitude() {
        return Latitude;
    }

    public void setLatitude(String latitude) {
        Latitude = latitude;
    }

    public String getLongitude() {
        return Longitude;
    }

    public void setLongitude(String longitude) {
        Longitude = longitude;
    }

    @Override
    public String toString() {
        return "GPS{" +
                "Latitude='" + Latitude + '\'' +
                ", Longitude='" + Longitude + '\'' +
                '}';
    }
} 

输出

 GPS{Latitude='40.741895', Longitude='-73.989308'} 

GPS::new调用下面的构造函数,它接受两个参数并返回一个对象(GPS ),因此它与BiFunction签名匹配。

 public GPS(String latitude, String longitude) {
        Latitude = latitude;
        Longitude = longitude;
    } 

4.更大的

4.1 通过一些条件过滤一个List

Java8BiFunction4.java

 package com.mkyong;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;

public class Java8BiFunction4 {

    public static void main(String[] args) {

        Java8BiFunction4 obj = new Java8BiFunction4();

        List<String> list = Arrays.asList("node", "c++", "java", "javascript");

        List<String> result = obj.filterList(list, 3, obj::filterByLength);

        System.out.println(result);   // [node, java, javascript]

        List<String> result1 = obj.filterList(list, 3, (l1, size) -> {
            if (l1.length() > size) {
                return l1;
            } else {
                return null;
            }
        });

        System.out.println(result1);  // [node, java, javascript]

        List<String> result2 = obj.filterList(list, "c", (l1, condition) -> {
            if (l1.startsWith(condition)) {
                return l1;
            } else {
                return null;
            }
        });

        System.out.println(result2);  // [c++]

        List<Integer> number = Arrays.asList(1, 2, 3, 4, 5);

        List<Integer> result3 = obj.filterList(number, 2, (l1, condition) -> {
            if (l1 % condition == 0) {
                return l1;
            } else {
                return null;
            }
        });

        System.out.println(result3);  // [2, 4]

    }

    public String filterByLength(String str, Integer size) {
        if (str.length() > size) {
            return str;
        } else {
            return null;
        }
    }

    public <T, U, R> List<R> filterList(List<T> list1, U condition,
                                        BiFunction<T, U, R> func) {

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

        for (T t : list1) {
            R apply = func.apply(t, condition);
            if (apply != null) {
                result.add(apply);
            }
        }

        return result;

    }

} 

输出

 [node, java, javascript]
[node, java, javascript]
[c++]
[2, 4] 

参考

Java 8 二进制运算符示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-binaryoperator-examples/

在 Java 8 中, BinaryOperator 是一个函数接口,它扩展了BiFunction

BinaryOperator接受两个相同类型的参数,并返回相同类型参数的结果。

BinaryOperator.java

 @FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> {
} 

BiFunction接受任意类型的两个参数,并返回任意类型的结果。

BiFunction.java

 @FunctionalInterface
public interface BiFunction<T, U, R> {
      R apply(T t, U u);
} 

1.二元运算符

1.1 在本例中,接受并返回相同类型的BiFunction<Integer, Integer, Integer>可以替换为BinaryOperator<Integer>

Java8BinaryOperator1.java

 package com.mkyong;

import java.util.function.BiFunction;
import java.util.function.BinaryOperator;

public class Java8BinaryOperator1 {

    public static void main(String[] args) {

        // BiFunction
        BiFunction<Integer, Integer, Integer> func = (x1, x2) -> x1 + x2;

        Integer result = func.apply(2, 3);

        System.out.println(result); // 5

        // BinaryOperator
        BinaryOperator<Integer> func2 = (x1, x2) -> x1 + x2;

        Integer result2 = func.apply(2, 3);

        System.out.println(result2); // 5

    }

} 

输出

 5
5 

2.BinaryOperator<T>作为参数

2.1 本例模拟一个stream.reduce()对所有Integer求和。

Java8BinaryOperator2.java

 package com.mkyong;

import java.util.Arrays;
import java.util.List;
import java.util.function.BinaryOperator;

public class Java8BinaryOperator2 {

    public static void main(String[] args) {

        Integer[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

        Integer result = math(Arrays.asList(numbers), 0, (a, b) -> a + b);

        System.out.println(result); // 55

        Integer result2 = math(Arrays.asList(numbers), 0, Integer::sum);

        System.out.println(result2); // 55

    }

    public static <T> T math(List<T> list, T init, BinaryOperator<T> accumulator) {
        T result = init;
        for (T t : list) {
            result = accumulator.apply(result, t);
        }
        return result;
    }

} 

输出

 55
55 

3.IntBinaryOperator

3.1 如果数学运算涉及到像int这样的基本类型,为了获得更好的性能,请更改为IntBinaryOperator

Java8BinaryOperator3.java

 package com.mkyong;

import java.util.function.IntBinaryOperator;
import java.util.stream.IntStream;

public class Java8BinaryOperator3 {

    public static void main(String[] args) {

        int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

        int result = math((numbers), 0, (a, b) -> a + b);

        System.out.println(result); // 55

        int result2 = math((numbers), 0, Integer::sum);

        System.out.println(result2); // 55

        IntStream
    }

    public static int math(int[] list, int init, IntBinaryOperator accumulator) {
        int result = init;
        for (int t : list) {
            result = accumulator.applyAsInt(result, t);
        }
        return result;
    }

} 

输出

 55
55 

4.BinaryOperator.maxBy()和 BinaryOperator.minBy()

4.1 这个例子使用了BinaryOperator和一个自定义的Comparator来从一个开发者列表中找到工资最高和最低的开发者。

Java8BinaryOperator4.java

 package com.mkyong;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.BinaryOperator;

public class Java8BinaryOperator4 {

    public static void main(String[] args) {

        Developer dev1 = new Developer("jordan", BigDecimal.valueOf(9999));
        Developer dev2 = new Developer("jack", BigDecimal.valueOf(8888));
        Developer dev3 = new Developer("jaden", BigDecimal.valueOf(10000));
        Developer dev4 = new Developer("ali", BigDecimal.valueOf(2000));
        Developer dev5 = new Developer("mkyong", BigDecimal.valueOf(1));

        List<Developer> list = Arrays.asList(dev1, dev2, dev3, dev4, dev5);

        // 1\. Create a Comparator
        Comparator<Developer> comparing = Comparator.comparing(Developer::getSalary);

        // 2\. BinaryOperator with a custom Comparator
        BinaryOperator<Developer> bo = BinaryOperator.maxBy(comparing);

        Developer result = find(list, bo);

        System.out.println(result);     // Developer{name='jaden', salary=10000}

        // one line

        // find developer with highest pay
        Developer developer = find(list, BinaryOperator.maxBy(Comparator.comparing(Developer::getSalary)));
        System.out.println(developer);  // Developer{name='jaden', salary=10000}

        // find developer with lowest pay
        Developer developer2 = find(list, BinaryOperator.minBy(Comparator.comparing(Developer::getSalary)));
        System.out.println(developer2); // Developer{name='mkyong', salary=1}

    }

    public static Developer find(List<Developer> list, BinaryOperator<Developer> accumulator) {
        Developer result = null;
        for (Developer t : list) {
            if (result == null) {
                result = t;
            } else {
                result = accumulator.apply(result, t);
            }
        }
        return result;
    }

} 

Developer.java

 package com.mkyong;

import java.math.BigDecimal;

public class Developer {

    String name;
    BigDecimal salary;

    public Developer(String name, BigDecimal salary) {
        this.name = name;
        this.salary = salary;
    }

    //...
} 

输出

 Developer{name='jaden', salary=10000}
Developer{name='jaden', salary=10000}
Developer{name='mkyong', salary=1} 

参考

Java 8 双预测示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-bipredicate-examples/

在 Java 8 中, BiPredicate 是一个函数接口,它接受两个参数并返回一个布尔值,基本上这个BiPredicatePredicate是一样的,但是它需要两个参数进行测试。

 @FunctionalInterface
public interface BiPredicate<T, U> {
    boolean test(T t, U u);
} 

延伸阅读
Java 8 谓词示例

1.双预测 Hello World。

如果字符串长度与提供的长度匹配。

JavaBiPredicate1.java

 package com.mkyong.java8;

import java.util.function.BiPredicate;

public class JavaBiPredicate1 {

    public static void main(String[] args) {

        BiPredicate<String, Integer> filter = (x, y) -> {
            return x.length() == y;
        };

        boolean result = filter.test("mkyong", 6);
        System.out.println(result);  // true

        boolean result2 = filter.test("java", 10);
        System.out.println(result2); // false
    }

} 

输出

 true
false 

2.双预测作为函数参数。

这个例子使用BiPredicate通过域名或威胁分值过滤坏域名。

JavaBiPredicate2.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;

public class JavaBiPredicate2 {

    public static void main(String[] args) {

        List<Domain> domains = Arrays.asList(new Domain("google.com", 1),
                new Domain("i-am-spammer.com", 10),
                new Domain("mkyong.com", 0),
                new Domain("microsoft.com", 2));

        BiPredicate<String, Integer> bi = (domain, score) -> {
            return (domain.equalsIgnoreCase("google.com") || score == 0);
        };

        // if google or score == 0
        List<Domain> result = filterBadDomain(domains, bi);
        System.out.println(result); // google.com, mkyong.com

        //  if score == 0
        List<Domain> result2 = filterBadDomain(domains, (domain, score) -> score == 0);
        System.out.println(result2); // mkyong.com, microsoft.com

        // if start with i or score > 5
        List<Domain> result3 = filterBadDomain(domains, (domain, score) -> domain.startsWith("i") && score > 5);
        System.out.println(result3); // i-am-spammer.com

        // chaining with or
        List<Domain> result4 = filterBadDomain(domains, bi.or(
                (domain, x) -> domain.equalsIgnoreCase("microsoft.com"))
        );
        System.out.println(result4); // google.com, mkyong.com, microsoft.com

    }

    public static <T extends Domain> List<T> filterBadDomain(
            List<T> list, BiPredicate<String, Integer> biPredicate) {

        return list.stream()
                .filter(x -> biPredicate.test(x.getName(), x.getScore()))
                .collect(Collectors.toList());

    }
}

class Domain {

    String name;
    Integer score;

    public Domain(String name, Integer score) {
        this.name = name;
        this.score = score;
    }
    // getters , setters , toString
} 

输出

 [Domain{name='google.com', score=1}, Domain{name='mkyong.com', score=0}]
[Domain{name='mkyong.com', score=0}]
[Domain{name='i-am-spammer.com', score=10}]
[Domain{name='google.com', score=1}, Domain{name='mkyong.com', score=0}, Domain{name='microsoft.com', score=2}] 

参考

Java 8–流收集器按示例分组

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-collectors-groupingby-and-mapping-example/

在本文中,我们将向您展示如何使用 Java 8 Stream Collectors对一个List进行分组、计数、求和以及排序。

1.分组依据、计数和排序

1.1 按 a List分组并显示其总数。

Java8Example1.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Java8Example1 {

    public static void main(String[] args) {

        //3 apple, 2 banana, others 1
        List<String> items =
                Arrays.asList("apple", "apple", "banana",
                        "apple", "orange", "banana", "papaya");

        Map<String, Long> result =
                items.stream().collect(
                        Collectors.groupingBy(
                                Function.identity(), Collectors.counting()
                        )
                );

        System.out.println(result);

    }
} 

输出

{
	papaya=1, orange=1, banana=2, apple=3
}

1.2 添加排序。

Java8Example2.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Java8Example2 {

    public static void main(String[] args) {

        //3 apple, 2 banana, others 1
        List<String> items =
                Arrays.asList("apple", "apple", "banana",
                        "apple", "orange", "banana", "papaya");

        Map<String, Long> result =
                items.stream().collect(
                        Collectors.groupingBy(
                                Function.identity(), Collectors.counting()
                        )
                );

        Map<String, Long> finalMap = new LinkedHashMap<>();

        //Sort a map and add to finalMap
        result.entrySet().stream()
                .sorted(Map.Entry.<String, Long>comparingByValue()
                        .reversed()).forEachOrdered(e -> finalMap.put(e.getKey(), e.getValue()));

        System.out.println(finalMap);

    }
} 

输出

{
	apple=3, banana=2, papaya=1, orange=1
}

2.列出对象

用户定义对象列表的“分组依据”示例。

2.1 A Pojo。

Item.java

 package com.mkyong.java8;

import java.math.BigDecimal;

public class Item {

    private String name;
    private int qty;
    private BigDecimal price;

    //constructors, getter/setters 
} 

2.2 按名称分组+计数或合计数量。

Java8Examples3.java

 package com.mkyong.java8;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Java8Examples3 {

    public static void main(String[] args) {

        //3 apple, 2 banana, others 1
        List<Item> items = Arrays.asList(
                new Item("apple", 10, new BigDecimal("9.99")),
                new Item("banana", 20, new BigDecimal("19.99")),
                new Item("orang", 10, new BigDecimal("29.99")),
                new Item("watermelon", 10, new BigDecimal("29.99")),
                new Item("papaya", 20, new BigDecimal("9.99")),
                new Item("apple", 10, new BigDecimal("9.99")),
                new Item("banana", 10, new BigDecimal("19.99")),
                new Item("apple", 20, new BigDecimal("9.99"))
        );

        Map<String, Long> counting = items.stream().collect(
                Collectors.groupingBy(Item::getName, Collectors.counting()));

        System.out.println(counting);

        Map<String, Integer> sum = items.stream().collect(
                Collectors.groupingBy(Item::getName, Collectors.summingInt(Item::getQty)));

        System.out.println(sum);

    }
} 

输出

//Group by + Count
{
	papaya=1, banana=2, apple=3, orang=1, watermelon=1
}

//Group by + Sum qty
{
	papaya=20, banana=30, apple=40, orang=10, watermelon=10
}

2.2 按价格分组—Collectors.groupingByCollectors.mapping示例。

Java8Examples4.java

 package com.mkyong.java8;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class Java8Examples4 {

    public static void main(String[] args) {

        //3 apple, 2 banana, others 1
        List<Item> items = Arrays.asList(
                new Item("apple", 10, new BigDecimal("9.99")),
                new Item("banana", 20, new BigDecimal("19.99")),
                new Item("orang", 10, new BigDecimal("29.99")),
                new Item("watermelon", 10, new BigDecimal("29.99")),
                new Item("papaya", 20, new BigDecimal("9.99")),
                new Item("apple", 10, new BigDecimal("9.99")),
                new Item("banana", 10, new BigDecimal("19.99")),
                new Item("apple", 20, new BigDecimal("9.99"))
                );

		//group by price
        Map<BigDecimal, List<Item>> groupByPriceMap = 
			items.stream().collect(Collectors.groupingBy(Item::getPrice));

        System.out.println(groupByPriceMap);

		// group by price, uses 'mapping' to convert List<Item> to Set<String>
        Map<BigDecimal, Set<String>> result =
                items.stream().collect(
                        Collectors.groupingBy(Item::getPrice,
                                Collectors.mapping(Item::getName, Collectors.toSet())
                        )
                );

        System.out.println(result);

    }
} 

输出

{
	19.99=[
			Item{name='banana', qty=20, price=19.99}, 
			Item{name='banana', qty=10, price=19.99}
		], 
	29.99=[
			Item{name='orang', qty=10, price=29.99}, 
			Item{name='watermelon', qty=10, price=29.99}
		], 
	9.99=[
			Item{name='apple', qty=10, price=9.99}, 
			Item{name='papaya', qty=20, price=9.99}, 
			Item{name='apple', qty=10, price=9.99}, 
			Item{name='apple', qty=20, price=9.99}
		]
}

//group by + mapping to Set
{
	19.99=[banana], 
	29.99=[orang, watermelon], 
	9.99=[papaya, apple]
}

参考

  1. Java 8 流收集器 JavaDoc
  2. Java–如何对地图进行排序
  3. stack overflow–按值排序映射<key value>(Java)

Tags : collectors group by java8 stream

Java 8 消费者示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-consumer-examples/

在 Java 8 中,消费者是一个函数接口;它接受一个参数,不返回任何值。

 @FunctionalInterface
public interface Consumer<T> {
  void accept(T t);
} 

1.消费者

Java8Consumer1.java

 package com.mkyong.java8;

import java.util.function.Consumer;

public class Java8Consumer1 {

    public static void main(String[] args) {

        Consumer<String> print = x -> System.out.println(x);
        print.accept("java");   // java

    }

} 

输出

 java 

2.高阶函数

2.1 这个例子接受Consumer作为参数,模拟一个forEach来打印列表中的每一项。

Java8Consumer2.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class Java8Consumer2 {

    public static void main(String[] args) {

        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);

        // implementation of the Consumer's accept methods.
        Consumer<Integer> consumer = (Integer x) -> System.out.println(x);
        forEach(list, consumer);

        // or call this directly
        forEach(list, (Integer x) -> System.out.println(x));

    }

    static <T> void forEach(List<T> list, Consumer<T> consumer) {
        for (T t : list) {
            consumer.accept(t);
        }
    }

} 

输出

 1
2
3
4
5
1
2
3
4
5 

2.2 同样的forEach方法接受Consumer作为参数;这一次,我们将打印字符串的长度。

Java8Consumer3.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class Java8Consumer3 {

    public static void main(String[] args) {

        List<String> list = Arrays.asList("a", "ab", "abc");
        forEach(list, (String x) -> System.out.println(x.length()));

    }

    static <T> void forEach(List<T> list, Consumer<T> consumer) {
        for (T t : list) {
            consumer.accept(t);
        }
    }

} 

输出

 1
2
3 

看到灵活性了吗?

参考

Java 8–将流转换为列表

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-convert-a-stream-to-list/

一个 Java 8 的例子,展示了如何通过Collectors.toListStream转换成List

Java8Example1.java

 package com.mkyong.java8;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Java8Example1 {

    public static void main(String[] args) {

        Stream<String> language = Stream.of("java", "python", "node");

        //Convert a Stream to List
        List<String> result = language.collect(Collectors.toList());

        result.forEach(System.out::println);

    }
} 

输出

 java
python
node 

还有一个例子,过滤一个数字 3 并将其转换成一个列表。

Java8Example2.java

 package com.mkyong.java8;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Java8Example2 {

    public static void main(String[] args) {

        Stream<Integer> number = Stream.of(1, 2, 3, 4, 5);

        List<Integer> result2 = number.filter(x -> x != 3).collect(Collectors.toList());

        result2.forEach(x -> System.out.println(x));

    }
} 

输出

 1
2
4
5 

参考

Tags : convert filter java 8 list stream

Java 8–将纪元时间毫秒转换为本地日期或本地日期时间

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-convert-epoch-time-milliseconds-to-localdate-or-localdatetime/

在 Java 8 中,我们可以使用Instant.ofEpochMilli().atZone()将以毫秒为单位的纪元时间转换回LocalDateLocalDateTime

历元时间至LocalDate

 LocalDate ld = Instant.ofEpochMilli(epoch).atZone(ZoneId.systemDefault()).toLocalDate(); 

历元时间至LocalDateTime

 LocalDateTime ldt = Instant.ofEpochMilli(epoch).atZone(ZoneId.systemDefault()).toLocalDateTime(); 

P . S . Epoch time 是自 1970 年 1 月 1 日世界协调时 0:00:00 起经过的秒数

1.epoch time-> localdate | | localdatetime

获取长值形式的当前历元时间,并将其转换回LocalDateLocalDateTime

Java8ConvertEpoch.java

 package com.mkyong.java8;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;

public class Java8ConvertEpoch {

    public static void main(String[] args) {

        long epoch = Instant.now().toEpochMilli();
        System.out.println(epoch);

        LocalDate ld = Instant.ofEpochMilli(epoch)
                .atZone(ZoneId.systemDefault()).toLocalDate();
        System.out.println(ld);

        LocalDateTime ldt = Instant.ofEpochMilli(epoch)
                .atZone(ZoneId.systemDefault()).toLocalDateTime();
        System.out.println(ldt);

    }

} 

输出

 1581420629955
2020-02-11
2020-02-11T19:30:29.955 

参考

Java 8–将即时转换为时区日期时间

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-convert-instant-to-zoneddatetime/

Java 8 示例向您展示如何从Instant转换到ZonedDateTime

1.即时->时区日期时间

Instant UTC+0 转换为日本ZonedDateTime UTC+9 的示例

InstantZonedDateTime1.java

 package com.mkyong.date;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class InstantZonedDateTime1 {

    public static void main(String[] argv) {

        // Z = UTC+0
        Instant instant = Instant.now();

        System.out.println("Instant : " + instant);

        // Japan = UTC+9
        ZonedDateTime jpTime = instant.atZone(ZoneId.of("Asia/Tokyo"));

        System.out.println("ZonedDateTime : " + jpTime);

        System.out.println("OffSet : " + jpTime.getOffset());

    }

} 

输出

 Instant : 2016-08-18T06:17:10.225Z
LocalDateTime : 2016-08-18T06:17:10.225 

2.ZonedDateTime ->即时

将日本的ZonedDateTime UTC+9 转换回一个Instant UTC+0/Z,查看结果,自动调整偏移量。

InstantZonedDateTime2.java

 package com.mkyong.date;

import java.time.*;

public class InstantZonedDateTime2 {

    public static void main(String[] argv) {

        LocalDateTime dateTime = LocalDateTime.of(2016, Month.AUGUST, 18, 6, 57, 38);

        // UTC+9
        ZonedDateTime jpTime = dateTime.atZone(ZoneId.of("Asia/Tokyo"));

        System.out.println("ZonedDateTime : " + jpTime);

        // Convert to instant UTC+0/Z , java.time helps to reduce 9 hours
        Instant instant = jpTime.toInstant();

        System.out.println("Instant : " + instant);

    }

} 

输出

 ZonedDateTime : 2016-08-18T06:57:38+09:00[Asia/Tokyo]
Instant : 2016-08-17T21:57:38Z 

参考

  1. 维基百科–ISO 8601 日期格式
  2. 即时 JavaDoc
  3. ZoneddateTime JavaDoc

Java 8–将列表转换为地图

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-convert-list-to-map/

几个 Java 8 示例向您展示如何将对象的List转换为Map,以及如何处理重复的键。

Hosting.java

 package com.mkyong.java8

public class Hosting {

    private int Id;
    private String name;
    private long websites;

    public Hosting(int id, String name, long websites) {
        Id = id;
        this.name = name;
        this.websites = websites;
    }

    //getters, setters and toString()
} 

1.要映射的列表–collectors . tomap()

创建一个Hosting对象的列表,并使用Collectors.toMap将其转换成地图。

TestListMap.java

 package com.mkyong.java8

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class TestListMap {

    public static void main(String[] args) {

        List<Hosting> list = new ArrayList<>();
        list.add(new Hosting(1, "liquidweb.com", 80000));
        list.add(new Hosting(2, "linode.com", 90000));
        list.add(new Hosting(3, "digitalocean.com", 120000));
        list.add(new Hosting(4, "aws.amazon.com", 200000));
        list.add(new Hosting(5, "mkyong.com", 1));

        // key = id, value - websites
        Map<Integer, String> result1 = list.stream().collect(
                Collectors.toMap(Hosting::getId, Hosting::getName));

        System.out.println("Result 1 : " + result1);

        // key = name, value - websites
        Map<String, Long> result2 = list.stream().collect(
                Collectors.toMap(Hosting::getName, Hosting::getWebsites));

        System.out.println("Result 2 : " + result2);

        // Same with result1, just different syntax
        // key = id, value = name
        Map<Integer, String> result3 = list.stream().collect(
                Collectors.toMap(x -> x.getId(), x -> x.getName()));

        System.out.println("Result 3 : " + result3);
    }
} 

输出

 Result 1 : {1=liquidweb.com, 2=linode.com, 3=digitalocean.com, 4=aws.amazon.com, 5=mkyong.com}
Result 2 : {liquidweb.com=80000, mkyong.com=1, digitalocean.com=120000, aws.amazon.com=200000, linode.com=90000}
Result 3 : {1=liquidweb.com, 2=linode.com, 3=digitalocean.com, 4=aws.amazon.com, 5=mkyong.com} 

2.要映射的列表-重复的键!

2.1 运行下面的代码,会抛出重复的键错误!

TestDuplicatedKey.java

 package com.mkyong.java8;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class TestDuplicatedKey {

    public static void main(String[] args) {

        List<Hosting> list = new ArrayList<>();
        list.add(new Hosting(1, "liquidweb.com", 80000));
        list.add(new Hosting(2, "linode.com", 90000));
        list.add(new Hosting(3, "digitalocean.com", 120000));
        list.add(new Hosting(4, "aws.amazon.com", 200000));
        list.add(new Hosting(5, "mkyong.com", 1));

        list.add(new Hosting(6, "linode.com", 100000)); // new line

        // key = name, value - websites , but the key 'linode' is duplicated!?
        Map<String, Long> result1 = list.stream().collect(
                Collectors.toMap(Hosting::getName, Hosting::getWebsites));

        System.out.println("Result 1 : " + result1);

    }
} 

输出——下面的错误信息有点误导,它应该显示“linode”而不是键值。

 Exception in thread "main" java.lang.IllegalStateException: Duplicate key 90000
	at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
	at java.util.HashMap.merge(HashMap.java:1245)
	//... 

2.2 要解决上面的重复键问题,请像这样传入第三个 mergeFunction 参数:

 Map<String, Long> result1 = list.stream().collect(
                Collectors.toMap(Hosting::getName, Hosting::getWebsites,
                        (oldValue, newValue) -> oldValue
                )
        ); 

输出

 Result 1 : {..., aws.amazon.com=200000, linode.com=90000} 

Note
(oldValue, newValue) -> oldValue ==> If the key is duplicated, do you prefer oldKey or newKey?

3.3 尝试新值

 Map<String, Long> result1 = list.stream().collect(
                Collectors.toMap(Hosting::getName, Hosting::getWebsites,
                        (oldValue, newValue) -> newvalue
                )
        ); 

输出

 Result 1 : {..., aws.amazon.com=200000, linode.com=100000} 

3.要映射的列表–排序和收集

TestSortCollect.java

 package com.mkyong.java8;

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

public class TestSortCollect {

    public static void main(String[] args) {

        List<Hosting> list = new ArrayList<>();
        list.add(new Hosting(1, "liquidweb.com", 80000));
        list.add(new Hosting(2, "linode.com", 90000));
        list.add(new Hosting(3, "digitalocean.com", 120000));
        list.add(new Hosting(4, "aws.amazon.com", 200000));
        list.add(new Hosting(5, "mkyong.com", 1));
        list.add(new Hosting(6, "linode.com", 100000));

        //example 1
        Map result1 = list.stream()
                .sorted(Comparator.comparingLong(Hosting::getWebsites).reversed())
                .collect(
                        Collectors.toMap(
                                Hosting::getName, Hosting::getWebsites, // key = name, value = websites
                                (oldValue, newValue) -> oldValue,       // if same key, take the old key
                                LinkedHashMap::new                      // returns a LinkedHashMap, keep order
                        ));

        System.out.println("Result 1 : " + result1);

    }
} 

输出

 Result 1 : {aws.amazon.com=200000, digitalocean.com=120000, linode.com=100000, liquidweb.com=80000, mkyong.com=1} 

在上面的例子中,流在收集之前被排序,所以“linode.com=100000”变成了“oldValue”。

参考

  1. Java 8 收集器 JavaDoc
  2. Java 8–如何对地图进行排序
  3. Java 8 Lambda:比较器示例

Java 8–将本地日期和本地日期时间转换为日期

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-convert-localdate-and-localdatetime-to-date/

一个将 Java 8 java.time.LocalDatejava.time.LocalDateTime转换回经典java.uti.Date的 Java 例子。

JavaDateExample.java

 package com.mkyong.time;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;

public class JavaDateExample {

    public static void main(String[] args) {

        // LocalDate -> Date
        LocalDate localDate = LocalDate.of(2020, 2, 20);
        Date date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());

        // LocalDateTime -> Date
        LocalDateTime localDateTime = LocalDateTime.of(2020,2,20,21,46,31);
        Date date2 = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());

        // ZonedDateTime -> Date
        ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
        Date date3 = Date.from(zonedDateTime.toInstant());

    }

} 

输出

 Thu Feb 20 00:00:00 MYT 2020
Thu Feb 20 21:46:31 MYT 2020
Thu Feb 20 21:46:31 MYT 2020 

Note
More examples – Java 8 – Convert Date to LocalDate and LocalDateTime

参考

Java 8–将本地日期时间转换为时间戳

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-convert-localdatetime-to-timestamp/

在 Java 中,我们可以使用Timestamp.valueOf(LocalDateTime)将一个LocalDateTime转换成一个Timestamp

1.localdatetime〔t0〕timestamp

Java 示例将java.time.LocalDateTime转换为java.sql.Timestamp,反之亦然。

TimeExample.java

 package com.mkyong;

import java.sql.Timestamp;
import java.time.LocalDateTime;

public class TimeExample {

    public static void main(String[] args) {

        //  LocalDateTime to Timestamp
        LocalDateTime now = LocalDateTime.now();
        Timestamp timestamp = Timestamp.valueOf(now);

        System.out.println(now);            // 2019-06-14T15:50:36.068076300
        System.out.println(timestamp);      // 2019-06-14 15:50:36.0680763

        //  Timestamp to LocalDateTime
        LocalDateTime localDateTime = timestamp.toLocalDateTime();

        System.out.println(localDateTime);  // 2019-06-14T15:50:36.068076300

    }
} 

2.LocalDate Timestamp

如题。

TimeExample2.java

 package com.mkyong.jdbc;

import java.sql.Timestamp;
import java.time.LocalDate;

public class TimeExample2 {

    public static void main(String[] args) {

        //  LocalDate to Timestamp
        LocalDate now = LocalDate.now();
        Timestamp timestamp = Timestamp.valueOf(now.atStartOfDay());

        System.out.println(now);        // 2019-06-14
        System.out.println(timestamp);  // 2019-06-14 00:00:00.0

        //  Timestamp to LocalDate
        LocalDate localDate = timestamp.toLocalDateTime().toLocalDate();
        System.out.println(localDate);  // 2019-06-14

    }
} 

参考

Tags : date conversion java 8 java.time

Java 8–将地图转换为列表

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-convert-map-to-list/

将一个Map转换成一个List的几个 Java 例子

 Map<String, String> map = new HashMap<>();

// Convert all Map keys to a List
List<String> result = new ArrayList(map.keySet());

// Convert all Map values to a List
List<String> result2 = new ArrayList(map.values());

// Java 8, Convert all Map keys to a List
List<String> result3 = map.keySet().stream()
	.collect(Collectors.toList());

// Java 8, Convert all Map values  to a List
List<String> result4 = map.values().stream()
	.collect(Collectors.toList());

// Java 8, seem a bit long, but you can enjoy the Stream features like filter and etc. 
List<String> result5 = map.values().stream()
	.filter(x -> !"apple".equalsIgnoreCase(x))
	.collect(Collectors.toList());

// Java 8, split a map into 2 List, it works!
// refer example 3 below 

1.映射到列表

对于简单的MapList的转换,只需使用下面的代码:

ConvertMapToList.java

 package com.mkyong;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ConvertMapToList {

    public static void main(String[] args) {

        Map<Integer, String> map = new HashMap<>();
        map.put(10, "apple");
        map.put(20, "orange");
        map.put(30, "banana");
        map.put(40, "watermelon");
        map.put(50, "dragonfruit");

        System.out.println("\n1\. Export Map Key to List...");

        List<Integer> result = new ArrayList(map.keySet());

        result.forEach(System.out::println);

        System.out.println("\n2\. Export Map Value to List...");

        List<String> result2 = new ArrayList(map.values());

        result2.forEach(System.out::println);

    }

} 

输出

 1\. Export Map Key to List...
50
20
40
10
30

2\. Export Map Value to List...
dragonfruit
orange
watermelon
apple
banana 

Java 8–映射到列表

对于 Java 8,您可以将Map转换成流,对其进行处理,并将其作为List返回

ConvertMapToList.java

 package com.mkyong;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class ConvertMapToList {

    public static void main(String[] args) {

        Map<Integer, String> map = new HashMap<>();
        map.put(10, "apple");
        map.put(20, "orange");
        map.put(30, "banana");
        map.put(40, "watermelon");
        map.put(50, "dragonfruit");

        System.out.println("\n1\. Export Map Key to List...");

        List<Integer> result = map.keySet().stream()
                .collect(Collectors.toList());

        result.forEach(System.out::println);

        System.out.println("\n2\. Export Map Value to List...");

        List<String> result2 = map.values().stream()
                .collect(Collectors.toList());

        result2.forEach(System.out::println);

        System.out.println("\n3\. Export Map Value to List..., say no to banana");
        List<String> result3 = map.keySet().stream()
                .filter(x -> !"banana".equalsIgnoreCase(x))
                .collect(Collectors.toList());

        result3.forEach(System.out::println);

    }

} 

输出

 1\. Export Map Key to List...
50
20
40
10
30

2\. Export Map Value to List...
dragonfruit
orange
watermelon
apple
banana

3\. Export Map Value to List..., say no to banana
dragonfruit
orange
watermelon
apple 

3.Java 8–将地图转换为 2 列表

这个例子有点极端,用map.entrySet()把一个Map转换成 2 个List

ConvertMapToList.java

 package com.mkyong;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

//https://www.mkyong.com/java8/java-8-how-to-sort-a-map/
public class ConvertMapToList {

    public static void main(String[] args) {

        Map<Integer, String> map = new HashMap<>();
        map.put(10, "apple");
        map.put(20, "orange");
        map.put(30, "banana");
        map.put(40, "watermelon");
        map.put(50, "dragonfruit");

        // split a map into 2 List
        List<Integer> resultSortedKey = new ArrayList<>();
        List<String> resultValues = map.entrySet().stream()
                //sort a Map by key and stored in resultSortedKey
                .sorted(Map.Entry.<Integer, String>comparingByKey().reversed())
                .peek(e -> resultSortedKey.add(e.getKey()))
                .map(x -> x.getValue())
                // filter banana and return it to resultValues
                .filter(x -> !"banana".equalsIgnoreCase(x))
                .collect(Collectors.toList());

        resultSortedKey.forEach(System.out::println);
        resultValues.forEach(System.out::println);

    }

} 

输出

 //resultSortedKey
50
40
30
20
10

//resultValues
dragonfruit
watermelon
orange
apple 

参考

  1. Java 8–将列表转换为映射
  2. Java 8 forEach 示例

convert java8 list map

Java 8–将 ZonedDateTime 转换为时间戳

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-convert-zoneddatetime-to-timestamp/

Java 示例将java.time.ZonedDateTime转换为java.sql.Timestamp,反之亦然。

1.ZonedDateTime ->时间戳

TimeExample1.java

 package com.mkyong.jdbc;

import java.sql.Timestamp;
import java.time.ZonedDateTime;

public class TimeExample1 {

    public static void main(String[] args) {

        ZonedDateTime now = ZonedDateTime.now();

        // 1\. ZonedDateTime to TimeStamp
        Timestamp timestamp = Timestamp.valueOf(now.toLocalDateTime());

        // 2\. ZonedDateTime to TimeStamp , no different
        Timestamp timestamp2 = Timestamp.from(now.toInstant());

        System.out.println(now);		// 2019-06-19T14:12:13.585294800+08:00[Asia/Kuala_Lumpur]

        System.out.println(timestamp);	// 2019-06-19 14:12:13.5852948

        System.out.println(timestamp2);	// 2019-06-19 14:12:13.5852948

    }
} 

输出

 2019-06-19T14:12:13.585294800+08:00[Asia/Kuala_Lumpur]
2019-06-19 14:12:13.5852948
2019-06-19 14:12:13.5852948 

2.时间戳->时区日期时间

TimeExample2.java

 package com.mkyong;

import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class TimeExample2 {

    public static void main(String[] args) {

        Timestamp timestamp = Timestamp.from(Instant.now());

        LocalDateTime localDateTimeNoTimeZone = timestamp.toLocalDateTime();

        ZonedDateTime zonedDateTime1 = localDateTimeNoTimeZone.atZone(ZoneId.of("+08:00"));

        ZonedDateTime zonedDateTime2 = localDateTimeNoTimeZone.atZone(ZoneId.of("Asia/Kuala_Lumpur"));

        ZonedDateTime zonedDateTime3 = localDateTimeNoTimeZone.atZone(ZoneId.systemDefault());

        ZonedDateTime zonedDateTime4 = localDateTimeNoTimeZone.atZone(ZoneId.of("-08:00"));

        System.out.println(timestamp);      // 2019-06-19 14:08:23.4458984

        System.out.println(zonedDateTime1); // 2019-06-19T14:08:23.445898400+08:00

        System.out.println(zonedDateTime2); // 2019-06-19T14:08:23.445898400+08:00[Asia/Kuala_Lumpur]

        System.out.println(zonedDateTime3); // 2019-06-19T14:08:23.445898400+08:00[Asia/Kuala_Lumpur]

        System.out.println(zonedDateTime4); // 2019-06-19T14:08:23.445898400-08:00

    }
} 

输出

 2019-06-19 14:08:23.4458984
2019-06-19T14:08:23.445898400+08:00
2019-06-19T14:08:23.445898400+08:00[Asia/Kuala_Lumpur]
2019-06-19T14:08:23.445898400+08:00[Asia/Kuala_Lumpur]
2019-06-19T14:08:23.445898400-08:00 

参考

Java 8–两个本地日期或本地日期时间之间的差异

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-difference-between-two-localdate-or-localdatetime/

在 Java 8 中,我们可以用PeriodDurationChronoUnit来计算两个LocalDateLocaldateTime的差值。

  1. Period计算两个LocalDate之差。
  2. Duration计算两个LocalDateTime之差。
  3. ChronoUnit为一切。

1.时期

JavaLocalDate.java

 package com.mkyong.java8;

import java.time.LocalDate;
import java.time.Period;

public class JavaLocalDate {

    public static void main(String[] args) {

        LocalDate from = LocalDate.of(2020, 5, 4);
        LocalDate to = LocalDate.of(2020, 10, 10);

        Period period = Period.between(from, to);

        System.out.print(period.getYears() + " years,");
        System.out.print(period.getMonths() + " months,");
        System.out.print(period.getDays() + " days");

    }

} 

输出

 0 years,5 months,6 days 

2.持续时间

JavaLocalDateTime.java

 package com.mkyong.java8;

import java.time.Duration;
import java.time.LocalDateTime;

public class JavaLocalDateTime {

    public static void main(String[] args) {

        LocalDateTime from = LocalDateTime.of(2020, 10, 4,
                10, 20, 55);
        LocalDateTime to = LocalDateTime.of(2020, 10, 10,
                10, 21, 1);

        Duration duration = Duration.between(from, to);

        // days between from and to
        System.out.println(duration.toDays() + " days");

        // hours between from and to
        System.out.println(duration.toHours() + " hours");

        // minutes between from and to
        System.out.println(duration.toMinutes() + " minutes");

        // seconds between from and to
        System.out.println(duration.toSeconds() + " seconds");
        System.out.println(duration.getSeconds() + " seconds");

    }

} 

输出

 6 days
144 hours
8640 minutes
518406 seconds
518406 seconds 

3.计时单位

JavaChronoUnit.java

 package com.mkyong.java8;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

public class JavaChronoUnit {

    public static void main(String[] args) {

        LocalDateTime from = LocalDateTime.of(2020, 10, 4,
                10, 20, 55);
        LocalDateTime to = LocalDateTime.of(2020, 11, 10,
                10, 21, 1);

        long years = ChronoUnit.YEARS.between(from, to);
        long months = ChronoUnit.MONTHS.between(from, to);
        long weeks = ChronoUnit.WEEKS.between(from, to);
        long days = ChronoUnit.DAYS.between(from, to);
        long hours = ChronoUnit.HOURS.between(from, to);
        long minutes = ChronoUnit.MINUTES.between(from, to);
        long seconds = ChronoUnit.SECONDS.between(from, to);
        long milliseconds = ChronoUnit.MILLIS.between(from, to);
        long nano = ChronoUnit.NANOS.between(from, to);

        System.out.println(years + " years");
        System.out.println(months + " months");
        System.out.println(weeks + " weeks");
        System.out.println(days + " days");
        System.out.println(hours + " hours");
        System.out.println(minutes + " minutes");
        System.out.println(seconds + " seconds");
        System.out.println(milliseconds + " milliseconds");
        System.out.println(nano + " nano");

    }

} 

输出

 0 years
1 months
5 weeks
37 days
888 hours
53280 minutes
3196806 seconds
3196806000 milliseconds
3196806000000000 nano 

参考

Java 8–过滤地图示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-filter-a-map-examples/

几个 Java 例子向你展示如何用 Java 8 stream API 过滤一个Map

Java 8 之前:

 Map<Integer, String> map = new HashMap<>();
    map.put(1, "linode.com");
    map.put(2, "heroku.com");

	String result = "";
	for (Map.Entry<Integer, String> entry : map.entrySet()) {
		if("something".equals(entry.getValue())){
			result = entry.getValue();
		}
	} 

使用 Java 8,你可以将一个Map.entrySet()转换成一个stream,然后是一个filter()collect() it。

 Map<Integer, String> map = new HashMap<>();
    map.put(1, "linode.com");
    map.put(2, "heroku.com");

	//Map -> Stream -> Filter -> String
	String result = map.entrySet().stream()
		.filter(x -> "something".equals(x.getValue()))
		.map(x->x.getValue())
		.collect(Collectors.joining());

	//Map -> Stream -> Filter -> MAP
	Map<Integer, String> collect = map.entrySet().stream()
		.filter(x -> x.getKey() == 2)
		.collect(Collectors.toMap(x -> x.getKey(), x -> x.getValue()));

	// or like this
	Map<Integer, String> collect = map.entrySet().stream()
		.filter(x -> x.getKey() == 3)
		.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); 

1.Java 8–过滤地图

按值过滤地图并返回字符串的完整示例。

TestMapFilter.java

 package com.mkyong;

import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class TestMapFilter {

    public static void main(String[] args) {

        Map<Integer, String> HOSTING = new HashMap<>();
        HOSTING.put(1, "linode.com");
        HOSTING.put(2, "heroku.com");
        HOSTING.put(3, "digitalocean.com");
        HOSTING.put(4, "aws.amazon.com");

        // Before Java 8
        String result = "";
        for (Map.Entry<Integer, String> entry : HOSTING.entrySet()) {
            if ("aws.amazon.com".equals(entry.getValue())) {
                result = entry.getValue();
            }
        }
        System.out.println("Before Java 8 : " + result);

        //Map -> Stream -> Filter -> String
        result = HOSTING.entrySet().stream()
                .filter(map -> "aws.amazon.com".equals(map.getValue()))
                .map(map -> map.getValue())
                .collect(Collectors.joining());

        System.out.println("With Java 8 : " + result);

        // filter more values
        result = HOSTING.entrySet().stream()
                .filter(x -> {
                    if (!x.getValue().contains("amazon") && !x.getValue().contains("digital")) {
                        return true;
                    }
                    return false;
                })
                .map(map -> map.getValue())
                .collect(Collectors.joining(","));

        System.out.println("With Java 8 : " + result);

    }

} 

输出

 Before Java 8 : aws.amazon.com
With Java 8 : aws.amazon.com
With Java 8 : linode.com,heroku.com 

2.Java 8–过滤地图#2

另一个例子是通过键过滤一个Map,但是这次将返回一个Map

TestMapFilter2.java

 package com.mkyong;

import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class TestMapFilter2 {

    public static void main(String[] args) {

        Map<Integer, String> HOSTING = new HashMap<>();
        HOSTING.put(1, "linode.com");
        HOSTING.put(2, "heroku.com");
        HOSTING.put(3, "digitalocean.com");
        HOSTING.put(4, "aws.amazon.com");

        //Map -> Stream -> Filter -> Map
        Map<Integer, String> collect = HOSTING.entrySet().stream()
                .filter(map -> map.getKey() == 2)
                .collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue()));

        System.out.println(collect); //output : {2=heroku.com}

        Map<Integer, String> collect2 = HOSTING.entrySet().stream()
                .filter(map -> map.getKey() <= 3)
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

        System.out.println(collect2); //output : {1=linode.com, 2=heroku.com, 3=digitalocean.com}

    }

} 

输出

 {2=heroku.com}
{1=linode.com, 2=heroku.com, 3=digitalocean.com} 

3.Java 8–过滤映射# 3–谓词

这一次,试试新的 Java 8 Predicate

TestMapFilter3.java

 package com.mkyong;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class TestMapFilter3 {

	// Generic Map filterbyvalue, with predicate
    public static <K, V> Map<K, V> filterByValue(Map<K, V> map, Predicate<V> predicate) {
        return map.entrySet()
                .stream()
                .filter(x -> predicate.test(x.getValue()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }

    public static void main(String[] args) {

        Map<Integer, String> HOSTING = new HashMap<>();
        HOSTING.put(1, "linode.com");
        HOSTING.put(2, "heroku.com");
        HOSTING.put(3, "digitalocean.com");
        HOSTING.put(4, "aws.amazon.com");
        HOSTING.put(5, "aws2.amazon.com");

        //  {1=linode.com}
        Map<Integer, String> filteredMap = filterByValue(HOSTING, x -> x.contains("linode"));
        System.out.println(filteredMap);

        // {1=linode.com, 4=aws.amazon.com, 5=aws2.amazon.com}
        Map<Integer, String> filteredMap2 = filterByValue(HOSTING, x -> (x.contains("aws") || x.contains("linode")));
        System.out.println(filteredMap2);

        // {4=aws.amazon.com}
        Map<Integer, String> filteredMap3 = filterByValue(HOSTING, x -> (x.contains("aws") && !x.contains("aws2")));
        System.out.println(filteredMap3);

        // {1=linode.com, 2=heroku.com}
        Map<Integer, String> filteredMap4 = filterByValue(HOSTING, x -> (x.length() <= 10));
        System.out.println(filteredMap4);

    }

} 

输出

 {1=linode.com}
{1=linode.com, 4=aws.amazon.com, 5=aws2.amazon.com}
{4=aws.amazon.com}
{1=linode.com, 2=heroku.com} 

参考

  1. 用 Java SE 8 流处理数据
  2. Java 收集器 JavaDoc
  3. Java 8 流过滤器示例

Tags : java8 map map filter predicate stream

Java 8–从流中过滤空值

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-filter-a-null-value-from-a-stream/

查看包含null值的Stream

Java8Examples.java

 package com.mkyong.java8;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Java8Examples {

    public static void main(String[] args) {

        Stream<String> language = Stream.of("java", "python", "node", null, "ruby", null, "php");

        List<String> result = language.collect(Collectors.toList());

        result.forEach(System.out::println);

    }
} 

输出

java
python
node
null   // <--- NULL
ruby
null   // <--- NULL
php

解决办法

为了解决这个问题,使用了Stream.filter(x -> x!=null)

Java8Examples.java

 package com.mkyong.java8;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Java8Examples {

    public static void main(String[] args) {

        Stream<String> language = Stream.of("java", "python", "node", null, "ruby", null, "php");

        //List<String> result = language.collect(Collectors.toList());

        List<String> result = language.filter(x -> x!=null).collect(Collectors.toList());

        result.forEach(System.out::println);

    }
} 

输出

java
python
node
ruby
php

或者,用Objects::nonNull过滤

 import java.util.List;

	List<String> result = language.filter(Objects::nonNull).collect(Collectors.toList()); 

参考

  1. Objects::非空 JavaDoc
  2. Java 8 流过滤器示例
  3. Java 8 收集器 JavaDoc

Java 8 平面图示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-flatmap-example/

本文解释了 Java 8 Stream.flatMap 以及如何使用它。

主题

  1. 什么是平面图?
  2. 为什么要平一条小溪?
  3. flatMap 示例–查找一套图书。
  4. 平面图示例–订单和行项目。
  5. 平面图示例–按空格分割线条。
  6. 平面图和原始类型

1。什么是 flatMap()?

1.1 回顾以下结构。它由 2 级流或 2d 阵列组成。

 # Stream<String[]>
# Stream<Stream<String>>
# String[][]

[
  [1, 2],
  [3, 4],
  [5, 6]
] 

在 Java 8 中,我们可以使用flatMap将上述两个级别的流转换为一个流级别,或将 2d 数组转换为 1d 数组。

 # Stream<String>
# String[]

[1, 2, 3, 4, 5, 6] 

2。为什么要平溪?

2.1 处理包含一个以上级别的流很有挑战性,例如Stream<String[]>Stream<List<LineItem>>Stream<Stream<String>>。我们将两个级别的流合并成一个级别,像Stream<String>Stream<LineItem>,这样我们就可以轻松地循环流并处理它。

查看以下示例,在流上应用flatMap之前和之后。

2.2 下面是一个 2d 数组,我们可以用Arrays.stream或者Stream.of将其转换成一个流,它产生一个String[]或者Stream<String[]>的流。

 String[][] array = new String[][]{{"a", "b"}, {"c", "d"}, {"e", "f"}};

  // array to a stream
  Stream<String[]> stream1 = Arrays.stream(array);

  // same result
  Stream<String[]> stream2 = Stream.of(array); 

或者像这样。

 [
  [a, b],
  [c, d],
  [e, f]
] 

2.3 这里是需求,我们要过滤掉a,打印出所有的字符。

首先,我们直接试试Stream#filter。但是,下面的程序什么都不会打印出来,这是因为Stream#filter里面的x是一个String[],而不是一个String;条件将始终保持为假,流将什么也不收集。

 String[][] array = new String[][]{{"a", "b"}, {"c", "d"}, {"e", "f"}};

  // convert array to a stream
  Stream<String[]> stream1 = Arrays.stream(array);

  List<String[]> result = stream1
      .filter(x -> !x.equals("a"))      // x is a String[], not String!
      .collect(Collectors.toList());

  System.out.println(result.size());    // 0

  result.forEach(System.out::println);  // print nothing? 

好了,这一次,我们重构 filter 方法来处理String[]

 String[][] array = new String[][]{{"a", "b"}, {"c", "d"}, {"e", "f"}};

  // array to a stream
  Stream<String[]> stream1 = Arrays.stream(array);

  // x is a String[]
  List<String[]> result = stream1
          .filter(x -> {
              for(String s : x){      // really?
                  if(s.equals("a")){
                      return false;
                  }
              }
              return true;
          }).collect(Collectors.toList());

  // print array
  result.forEach(x -> System.out.println(Arrays.toString(x))); 

输出

Terminal

 [c, d]
[e, f] 

在上面的例子中,Stream#filter将过滤掉整个[a, b],但是我们只想过滤掉字符a

下面的 3.4 是最终版本,我们先组合数组,然后是过滤器。在 Java 中,要把一个 2d 数组转换成 1d 数组,我们可以循环 2d 数组,把所有的元素放到一个新数组中;或者我们可以用 Java 8 flatMap把 2d 数组扁平化成 1d 数组,或者从Stream<String[]>Stream<String>

 String[][] array = new String[][]{{"a", "b"}, {"c", "d"}, {"e", "f"}};

  // Java 8
  String[] result = Stream.of(array)  // Stream<String[]>
          .flatMap(Stream::of)        // Stream<String>
          .toArray(String[]::new);    // [a, b, c, d, e, f]

  for (String s : result) {
      System.out.println(s);
  } 

输出

Terminal

 a
b
c
d
e
f 

现在,我们可以很容易地过滤掉a;让我们看看最终版本。

 String[][] array = new String[][]{{"a", "b"}, {"c", "d"}, {"e", "f"}};

  List<String> collect = Stream.of(array)     // Stream<String[]>
          .flatMap(Stream::of)                // Stream<String>
          .filter(x -> !"a".equals(x))        // filter out the a
          .collect(Collectors.toList());      // return a List

  collect.forEach(System.out::println); 

输出

Terminal

 b
c
d
e
f 

我想指出的是,处理多于一个级别的流是具有挑战性的,令人困惑,并且容易出错,我们可以使用这个Stream#flatMap将 2 个级别的流展平为一个级别的流。

 Stream<String[]>      -> flatMap ->	Stream<String>
Stream<Set<String>>   -> flatMap ->	Stream<String>
Stream<List<String>>  -> flatMap ->	Stream<String>
Stream<List<Object>>  -> flatMap ->	Stream<Object> 

3。平面图示例-查找所有书籍。

这个例子使用.stream()将一个List转换成一个对象流,每个对象包含一套书,我们可以使用flatMap产生一个包含所有对象中所有书的流。

最后,我们还过滤掉包含单词python的书,并收集一个Set来移除重复的书。

Developer.java

 package com.mkyong.java8.stream.flatmap;

import java.util.HashSet;
import java.util.Set;

public class Developer {

    private Integer id;
    private String name;
    private Set<String> book;

    //getters, setters, toString

    public void addBook(String book) {
        if (this.book == null) {
            this.book = new HashSet<>();
        }
        this.book.add(book);
    }
} 

FlatMapExample1.java

 package com.mkyong.java8.stream.flatmap;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class FlatMapExample1 {

    public static void main(String[] args) {

        Developer o1 = new Developer();
        o1.setName("mkyong");
        o1.addBook("Java 8 in Action");
        o1.addBook("Spring Boot in Action");
        o1.addBook("Effective Java (3nd Edition)");

        Developer o2 = new Developer();
        o2.setName("zilap");
        o2.addBook("Learning Python, 5th Edition");
        o2.addBook("Effective Java (3nd Edition)");

        List<Developer> list = new ArrayList<>();
        list.add(o1);
        list.add(o2);

        // hmm....Set of Set...how to process?
        /*Set<Set<String>> collect = list.stream()
                .map(x -> x.getBook())
                .collect(Collectors.toSet());*/

        Set<String> collect =
                list.stream()
                        .map(x -> x.getBook())                              //  Stream<Set<String>>
                        .flatMap(x -> x.stream())                           //  Stream<String>
                        .filter(x -> !x.toLowerCase().contains("python"))   //  filter python book
                        .collect(Collectors.toSet());                       //  remove duplicated

        collect.forEach(System.out::println);

    }

} 

输出

Terminal

 Spring Boot in Action
Effective Java (3nd Edition)
Java 8 in Action 

map是可选的。

 Set<String> collect2 = list.stream()
                    //.map(x -> x.getBook())
                    .flatMap(x -> x.getBook().stream())                 //  Stream<String>
                    .filter(x -> !x.toLowerCase().contains("python"))   //  filter python book
                    .collect(Collectors.toSet()); 

4。平面图示例–订单和行项目

这个例子类似于官方的 flatMap JavaDoc 例子。

orders是一个购买订单流,每个购买订单包含一组行项目,然后我们可以使用flatMap产生一个包含所有订单中所有行项目的流或Stream<LineItem>。此外,我们还添加了一个reduce操作来合计行项目的总金额。

FlatMapExample2.java

 package com.mkyong.java8.stream.flatmap;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;

public class FlatMapExample2 {

    public static void main(String[] args) {

        List<Order> orders = findAll();

        /*
            Stream<List<LineItem>> listStream = orders.stream()
                    .map(order -> order.getLineItems());

            Stream<LineItem> lineItemStream = orders.stream()
                    .flatMap(order -> order.getLineItems().stream());
        */

        // sum the line items' total amount
        BigDecimal sumOfLineItems = orders.stream()
                .flatMap(order -> order.getLineItems().stream())    //  Stream<LineItem>
                .map(line -> line.getTotal())                       //  Stream<BigDecimal>
                .reduce(BigDecimal.ZERO, BigDecimal::add);          //  reduce to sum all

        // sum the order's total amount
        BigDecimal sumOfOrder = orders.stream()
                .map(order -> order.getTotal())                     //  Stream<BigDecimal>
                .reduce(BigDecimal.ZERO, BigDecimal::add);          //  reduce to sum all

        System.out.println(sumOfLineItems);                         // 3194.20
        System.out.println(sumOfOrder);                             // 3194.20

        if (!sumOfOrder.equals(sumOfLineItems)) {
            System.out.println("The sumOfOrder is not equals to sumOfLineItems!");
        }

    }

    // create dummy records
    private static List<Order> findAll() {

        LineItem item1 = new LineItem(1, "apple", 1, new BigDecimal("1.20"), new BigDecimal("1.20"));
        LineItem item2 = new LineItem(2, "orange", 2, new BigDecimal(".50"), new BigDecimal("1.00"));
        Order order1 = new Order(1, "A0000001", Arrays.asList(item1, item2), new BigDecimal("2.20"));

        LineItem item3 = new LineItem(3, "monitor BenQ", 5, new BigDecimal("99.00"), new BigDecimal("495.00"));
        LineItem item4 = new LineItem(4, "monitor LG", 10, new BigDecimal("120.00"), new BigDecimal("1200.00"));
        Order order2 = new Order(2, "A0000002", Arrays.asList(item3, item4), new BigDecimal("1695.00"));

        LineItem item5 = new LineItem(5, "One Plus 8T", 3, new BigDecimal("499.00"), new BigDecimal("1497.00"));
        Order order3 = new Order(3, "A0000003", Arrays.asList(item5), new BigDecimal("1497.00"));

        return Arrays.asList(order1, order2, order3);

    }
} 

Order.java

 public class Order {

    private Integer id;
    private String invoice;
    private List<LineItem> lineItems;
    private BigDecimal total;

    // getter, setters, constructor
} 

LineItem.java

 public class LineItem {

    private Integer id;
    private String item;
    private Integer qty;
    private BigDecimal price;
    private BigDecimal total;

    // getter, setters, constructor
} 

输出

Terminal

 3194.20
3194.20 

5。平面图示例–用空格分割线条

这个例子读取了一个文本文件,用空格分割了一行,并显示了单词的总数。

一个文本文件。

c:\test\test.txt

 hello world Java
hello world Python
hello world Node JS
hello world Rust
hello world Flutter 

阅读评论,不言自明。

FlatMapExample3.java

 package com.mkyong.java8.stream.flatmap;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;

public class FlatMapExample3 {

    public static void main(String[] args) throws IOException {

        Path path = Paths.get("C:\\test\\test.txt");

        // read file into a stream of lines
        Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8);

        // stream of array...hard to process.
        // Stream<String[]> words = lines.map(line -> line.split(" +"));

        // stream of stream of string....hmm...better flat to one level.
        // Stream<Stream<String>> words = lines.map(line -> Stream.of(line.split(" +")));

        // result a stream of words, good!
        Stream<String> words = lines.flatMap(line -> Stream.of(line.split(" +")));

        // count the number of words.
        long noOfWords = words.count();

        System.out.println(noOfWords);  // 16
    }
} 

输出

Terminal

 16 

6。平面图和原始类型

对于原始类型,如intlongdouble等。Java 8 流也提供相关的flatMapTo{primative type}来扁平化原语类型的流;概念是一样的。

flatMapToInt->-IntStream

FlatMapExample4.java

 package com.mkyong.java8.stream.flatmap;

import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class FlatMapExample4 {

    public static void main(String[] args) {

        int[] array = {1, 2, 3, 4, 5, 6};

        //Stream<int[]>
        Stream<int[]> streamArray = Stream.of(array);

        //Stream<int[]> -> flatMap -> IntStream
        IntStream intStream = streamArray.flatMapToInt(x -> Arrays.stream(x));

        intStream.forEach(x -> System.out.println(x));

    }
} 

输出

Terminal

 1
2
3
4
5
6 

flatMapToLong->-LongStream

 long[] array = {1, 2, 3, 4, 5, 6};

  Stream<long[]> longArray = Stream.of(array);

  LongStream longStream = longArray.flatMapToLong(x -> Arrays.stream(x));

  System.out.println(longStream.count()); 

下载源代码

$ git 克隆https://github.com/mkyong/core-java

$ cd java8

参考文献

Java 8 forEach 示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-foreach-examples/

在 Java 8 中,我们可以使用新的forEach来循环或迭代一个MapListSetStream

主题

  1. 循环地图
  2. 循环列表
  3. forEach 和 Consumer
  4. forEach 和异常处理
  5. forEach vs forEachOrdered

1。循环地图

1.1 下面是循环 a Map的正常方式。

 public static void loopMapClassic() {

      Map<String, Integer> map = new HashMap<>();
      map.put("A", 10);
      map.put("B", 20);
      map.put("C", 30);
      map.put("D", 40);
      map.put("E", 50);
      map.put("F", 60);

      for (Map.Entry<String, Integer> entry : map.entrySet()) {
          System.out.println("Key : " + entry.getKey() + ", Value : " + entry.getValue());
      }

  } 

1.2 在 Java 8 中,我们可以使用forEach来循环一个Map并打印出它的条目。

 public static void loopMapJava8() {

      Map<String, Integer> map = new HashMap<>();
      map.put("A", 10);
      map.put("B", 20);
      map.put("C", 30);
      map.put("D", 40);
      map.put("E", 50);
      map.put("F", 60);

      // lambda
      map.forEach((k, v) -> System.out.println("Key : " + k + ", Value : " + v));

  } 

输出

Terminal

 Key : A, Value : 10
Key : B, Value : 20
Key : C, Value : 30
Key : D, Value : 40
Key : E, Value : 50
Key : F, Value : 60 

1.3 对于Map包含null的键或值,forEach将打印null

 public static void loopMapJava8() {

      Map<String, Integer> map = new HashMap<>();
      map.put("A", 10);
      map.put("B", 20);
      map.put("C", 30);
      map.put(null, 40);
      map.put("E", null);
      map.put("F", 60);

      // ensure map is not null
      if (map != null) {
          map.forEach((k, v) -> System.out.println("Key : " + k + ", Value : " + v));
      }

  } 

输出

Terminal

 Key : null, Value : 40
Key : A, Value : 10
Key : B, Value : 20
Key : C, Value : 30
Key : E, Value : null
Key : F, Value : 60 

P.S 循环 a Map的正常方式将打印与上面相同的输出。

1.4 如果我们不想打印null键,在forEach内添加一个简单的空值检查。

 public static void loopMapJava8() {

      Map<String, Integer> map = new HashMap<>();
      map.put("A", 10);
      map.put("B", 20);
      map.put("C", 30);
      map.put(null, 40);
      map.put("E", null);
      map.put("F", 60);

      map.forEach(
          (k, v) -> {
              // yes, we can put logic here
              if (k != null){
                  System.out.println("Key : " + k + ", Value : " + v);
              }
          }
      );

  } 

输出

Terminal

 Key : A, Value : 10
Key : B, Value : 20
Key : C, Value : 30
Key : E, Value : null
Key : F, Value : 60 

2。循环列表

2.1 下面是循环 a List的正常方式。

 public static void loopListClassic() {

      List<String> list = new ArrayList<>();
      list.add("A");
      list.add("B");
      list.add("C");
      list.add("D");
      list.add("E");

      // normal loop
      for (String l : list) {
          System.out.println(l);
      }

  } 

2.2 Java 8 forEach来循环一个List

 public static void loopListJava8() {

      List<String> list = new ArrayList<>();
      list.add("A");
      list.add("B");
      list.add("C");
      list.add("D");
      list.add("E");

      // lambda
      // list.forEach(x -> System.out.println(x));

      // method reference
      list.forEach(System.out::println);
  } 

输出

Terminal

 A
B
C
D
E 

2.3 这个例子过滤了一个List的空值。

 public static void loopListJava8() {

      List<String> list = new ArrayList<>();
      list.add("A");
      list.add("B");
      list.add(null);
      list.add("D");
      list.add("E");

      // filter null value
      list.stream()
              .filter(Objects::nonNull)
              .forEach(System.out::println);

  } 

输出

Terminal

 A
B
D
E 

附注:SetStreamforEach工作方式相同。

3。forEach 和 Consumer

3.1 检查forEach方法签名,它接受一个函数接口消费者

Iterable.java

 public interface Iterable<T> {

  default void forEach(Consumer<? super T> action) {
      Objects.requireNonNull(action);
      for (T t : this) {
          action.accept(t);
      }
  }
  //..
} 

Stream.java

 public interface Stream<T> extends BaseStream<T, Stream<T>> {

  void forEach(Consumer<? super T> action);
  //...

} 

3.2 本例创建了一个Consumer方法,将字符串打印成十六进制格式。我们现在可以重用同一个Consumer方法,并将其传递给ListStreamforEach方法。

ForEachConsumer.java

 package com.mkyong.java8.misc;

import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Stream;

public class ForEachConsumer {

    public static void main(String[] args) {

        List<String> list = Arrays.asList("abc", "java", "python");
        Stream<String> stream = Stream.of("abc", "java", "python");

        // convert a String to a Hex
        Consumer<String> printTextInHexConsumer = (String x) -> {
            StringBuilder sb = new StringBuilder();
            for (char c : x.toCharArray()) {
                String hex = Integer.toHexString(c);
                sb.append(hex);
            }
            System.out.print(String.format("%n%-10s:%s", x, sb.toString()));
        };

        // pass a Consumer
        list.forEach(printTextInHexConsumer);

        stream.forEach(printTextInHexConsumer);

    }

} 

输出

Terminal

 abc       :616263
java      :6a617661
python    :707974686f6e

abc       :616263
java      :6a617661
python    :707974686f6e 

4。forEach 和异常处理。

4.1forEach不仅仅是为了打印,这个例子展示了如何使用forEach方法循环一个对象列表并将其写入文件。

ForEachWriteFile.java

 package com.mkyong.java8.misc;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;

public class ForEachWriteFile {

    public static void main(String[] args) {

        ForEachWriteFile obj = new ForEachWriteFile();
        obj.save(Paths.get("C:\\test"), obj.createDummyFiles());
    }

    public void save(Path path, List<DummyFile> files) {

        if (!Files.isDirectory(path)) {
            throw new IllegalArgumentException("Path must be a directory");
        }

        files.forEach(f -> {
            try {
                int id = f.getId();
                // create a filename
                String fileName = id + ".txt";
                Files.write(path.resolve(fileName),
                        f.getContent().getBytes(StandardCharsets.UTF_8));
            } catch (IOException e) {
                e.printStackTrace();
            }
        });

    }

    public List<DummyFile> createDummyFiles() {
        return Arrays.asList(
                new DummyFile(1, "hello"),
                new DummyFile(2, "world"),
                new DummyFile(3, "java"));
    }

    class DummyFile {
        int id;
        String content;

        public DummyFile(int id, String content) {
            this.id = id;
            this.content = content;
        }

        public int getId() {
            return id;
        }

        public String getContent() {
            return content;
        }
    }
} 

上面的程序将创建三个文本文件。

C:\test\1.txt

 hello 

C:\test\2.txt

 world 

C:\test\3.txt

 java 

4.2Files.write可能抛出IOException,我们必须捕捉到forEach内部的异常;因此,代码看起来很难看。通常的做法是将代码提取到一个新方法中。

 public void save(Path path, List<DummyFile> files) {

      if (!Files.isDirectory(path)) {
          throw new IllegalArgumentException("Path must be a directory");
      }

      // extract it to a new method
      /*files.forEach(f -> {
            try {
                int id = f.getId();
                // create a filename
                String fileName = id + ".txt";
                Files.write(path.resolve(fileName),
                        f.getContent().getBytes(StandardCharsets.UTF_8));
            } catch (IOException e) {
                e.printStackTrace();
            }
        });*/

      // nice!
      files.forEach(f -> saveFile(path, f));

  }

  public void saveFile(Path path, DummyFile f) {
      try {
          int id = f.getId();
          // create a filename
          String fileName = id + ".txt";
          Files.write(path.resolve(fileName),
                  f.getContent().getBytes(StandardCharsets.UTF_8));
      } catch (IOException e) {
          e.printStackTrace();
      }
  } 

现在,我们也可以编写这样的代码:

 ForEachWriteFile obj = new ForEachWriteFile();

  Path path = Paths.get("C:\\test");
  obj.createDummyFiles().forEach(o -> obj.saveFile(path, o)); 

5。forEach vs forEachOrdered

5.1forEach不保证流的相遇顺序,不管流是顺序的还是并行的。当以并行模式运行时,结果很明显。

 Stream<String> s = Stream.of("a", "b", "c", "1", "2", "3");
  s.parallel().forEach(x -> System.out.println(x)); 

每次运行将产生不同的结果:

Terminal

 1
2
b
c
3
a 

5.2forEachOrdered保证流的相遇顺序;因此,它牺牲了并行性的好处。

 Stream<String> s = Stream.of("a", "b", "c", "1", "2", "3");
  // keep order, it is always a,b,c,1,2,3
  s.parallel().forEachOrdered(x -> System.out.println(x)); 

结果总是a,b,c,1,2,3

Terminal

 a
b
c
1
2
3 

下载源代码

$ git 克隆https://github.com/mkyong/core-java

$ cd java8

参考文献

带索引的 Java 8 forEach 打印

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-foreach-print-with-index/

一个简单的 Java 8 技巧来打印前面带有索引的ArrayList

1.带索引的数组

IntStream.range生成索引。

JavaListWithIndex.java

 package com.mkyong.java8;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class JavaArrayWithIndex {

    public static void main(String[] args) {

        String[] names = {"Java", "Node", "JavaScript", "Rust", "Go"};

        List<String> collect = IntStream.range(0, names.length)
                .mapToObj(index -> index + ":" + names[index])
                .collect(Collectors.toList());

        collect.forEach(System.out::println);

    }

} 

输出

 0:Java
1:Node
2:JavaScript
3:Rust
4:Go 

2.带索引的列表

List转换为Map,并使用Map.size作为索引。

Stream.java

 <R> R collect(Supplier<R> supplier,
                  BiConsumer<R, ? super T> accumulator,
                  BiConsumer<R, R> combiner); 

JavaListWithIndex.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

public class JavaListWithIndex {

    public static void main(String[] args) {

        List<String> list = Arrays.asList("Java", "Node", "JavaScript", "Rust", "Go");

        HashMap<Integer, String> collect = list
                .stream()
                .collect(HashMap<Integer, String>::new,
                        (map, streamValue) -> map.put(map.size(), streamValue),
                        (map, map2) -> {
                        });

        collect.forEach((k, v) -> System.out.println(k + ":" + v));

    }

} 

输出

 0:Java
1:Node
2:JavaScript
3:Rust
4:Go 

参考

Java 8 函数示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-function-examples/

在 Java 8 中,函数是一个函数接口;它接受一个参数(T 类型的对象)并返回一个对象(R 类型的对象)。参数和输出可以是不同的类型。

Function.java

 @FunctionalInterface
public interface Function<T, R> {

      R apply(T t);

} 
  • t–函数输入的类型。
  • r–函数结果的类型。

Further Reading
Java 8 BiFunction Examples

1.功能

1.1 本例采用一个<T> String并将字符串的长度返回为<R> Integer

Java8Function1.java

 package com.mkyong;

import java.util.function.Function;

public class JavaMoney {

    public static void main(String[] args) {

        Function<String, Integer> func = x -> x.length();

        Integer apply = func.apply("mkyong");   // 6

        System.out.println(apply);

    }

} 

输出

 6 

2.连锁功能

2.1 本例将FunctionandThen()链接起来。

Java8Function2.java

 package com.mkyong;

import java.util.function.Function;

public class Java8Function2 {

    public static void main(String[] args) {

        Function<String, Integer> func = x -> x.length();

        Function<Integer, Integer> func2 = x -> x * 2;

        Integer result = func.andThen(func2).apply("mkyong");   // 12

        System.out.println(result);

    }

} 

输出

 12 

3.列表->地图

3.1 这个例子接受Function作为参数,将一个List转换成一个Map

Java8Function3.java

 package com.mkyong;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

public class Java8Function3 {

    public static void main(String[] args) {

        Java8Function3 obj = new Java8Function3();

        List<String> list = Arrays.asList("node", "c++", "java", "javascript");

        // lambda
        Map<String, Integer> map = obj.convertListToMap(list, x -> x.length());

        System.out.println(map);    // {node=4, c++=3, java=4, javascript=10}

        // method reference
        Map<String, Integer> map2 = obj.convertListToMap(list, obj::getLength);

        System.out.println(map2);
    }

    public <T, R> Map<T, R> convertListToMap(List<T> list, Function<T, R> func) {

        Map<T, R> result = new HashMap<>();
        for (T t : list) {
            result.put(t, func.apply(t));
        }
        return result;

    }

    public Integer getLength(String str) {
        return str.length();
    }

} 

输出

 {node=4, c++=3, java=4, javascript=10}
{node=4, c++=3, java=4, javascript=10} 

4.列表->列表

4.1 这个例子接受Function作为一个参数,将一个字符串的List转换成另一个字符串的List,用 SHA256 散列。

Java8Function4

 package com.mkyong;

import org.apache.commons.codec.digest.DigestUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

public class Java8Function4 {

    public static void main(String[] args) {

        Java8Function4 obj = new Java8Function4();

        List<String> list = Arrays.asList("node", "c++", "java", "javascript");

        // lambda
        //List<String> result = obj.map(list, x -> obj.sha256(x));

        // method reference
        List<String> result = obj.map(list, obj::sha256);

        result.forEach(System.out::println);

    }

    public <T, R> List<R> map(List<T> list, Function<T, R> func) {

        List<R> result = new ArrayList<>();
        for (T t : list) {
            result.add(func.apply(t));
        }
        return result;

    }

    // sha256 a string
    public String sha256(String str) {
        return DigestUtils.sha256Hex(str);
    }

} 

输出

 545ea538461003efdc8c81c244531b003f6f26cfccf6c0073b3239fdedf49446
cedb1bac7efcd7db47e9f2f2250a7c832aba83b410dd85766e2aea6ec9321e51
38a0963a6364b09ad867aa9a66c6d009673c21e182015461da236ec361877f77
eda71746c01c3f465ffd02b6da15a6518e6fbc8f06f1ac525be193be5507069d 

附注:DigestUtils.sha256Hex来自commons-codec

pom.xml

 <dependency>
  <groupId>commons-codec</groupId>
  <artifactId>commons-codec</artifactId>
  <version>1.14</version>
</dependency> 

参考

Java 8–HijrahDate,如何计算斋月日期

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-hijrahdate-how-to-calculate-the-ramadan-date/

斋月是伊斯兰历的第九个月,整月。

1.回历-> 2016 年斋月

计算 2016 年斋月开始和结束的完整示例

TestHijrahDate.java

 package com.mkyong.date;

import java.time.LocalDate;
import java.time.chrono.HijrahDate;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAdjusters;

public class TestDate {

    public static void main(String[] args) {

        //first day of Ramadan, 9th month
        HijrahDate ramadan = HijrahDate.now()
                .with(ChronoField.DAY_OF_MONTH, 1).with(ChronoField.MONTH_OF_YEAR, 9);
        System.out.println("HijrahDate : " + ramadan);

        //HijrahDate -> LocalDate
        System.out.println("\n--- Ramandan 2016 ---");
        System.out.println("Start : " + LocalDate.from(ramadan));

        //until the end of the month
        System.out.println("End : " + LocalDate.from(ramadan.with(TemporalAdjusters.lastDayOfMonth())));

    }

} 

输出

 HijrahDate : Hijrah-umalqura AH 1437-09-01

--- Ramandan 2016 ---
Start : 2016-06-06
End : 2016-07-05 

参考

  1. 维基百科–斋月(日历月)
  2. HijrahDate JavaDoc

hijrah java.time java8 ramadan (function (i,d,s,o,m,r,c,l,w,q,y,h,g) { var e=d.getElementById(r);if(e=null){ var t = d.createElement(o); t.src = g; t.id = r; t.setAttribute(m, s);t.async = 1;var n=d.getElementsByTagName(o)[0];n.parentNode.insertBefore(t, n); var dt=new Date().getTime(); try{i[l]w+y;}catch(er){i[h]=dt;} } else if(typeof i[c]!'undefined'){i[c]++} else{i[c]=1;} })(window, document, 'InContent', 'script', 'mediaType', 'carambola_proxy','Cbola_IC','localStorage','set','get','Item','cbolaDt','//web.archive.org/web/20190225092841/http://route.carambo.la/inimage/getlayer?pid=myky82&did=112239&wid=0')

Java 8–如何计算两个日期之间的天数?

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-how-to-calculate-days-between-two-dates/

在 Java 8 中,我们可以使用ChronoUnit.DAYS.between(from, to)来计算两个日期之间的天数。

1.局部日期

JavaBetweenDays1.java

 package com.mkyong.java8;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

public class JavaBetweenDays1 {

    public static void main(String[] args) {

        LocalDate from = LocalDate.now();
        LocalDate to = from.plusDays(10);

        long result = ChronoUnit.DAYS.between(from, to);
        System.out.println(result);    // 10

    }

} 

输出

 10 

2.本地日期时间

JavaBetweenDays2.java

 package com.mkyong.java8;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

public class JavaBetweenDays2 {

    public static void main(String[] args) {

        LocalDateTime from = LocalDateTime.now();
        LocalDateTime to = from.plusDays(10);

        long result = ChronoUnit.DAYS.between(from, to);
        System.out.println(result);     // 10

        LocalDateTime to2 = from.minusDays(10);
        long result2 = ChronoUnit.DAYS.between(from, to2);
        System.out.println(result2);    // -10

    }

} 

输出

 10
-10 

参考

Java 8–将流转换为数组

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-how-to-convert-a-stream-to-array/

在 Java 8 中,我们可以使用.toArray()将流转换成数组。

1.流->字符串[]

StreamString.java

 package com.mkyong;

import java.util.Arrays;

public class StreamString {

    public static void main(String[] args) {

        String lines = "I Love Java 8 Stream!";

        // split by space, uppercase, and convert to Array
        String[] result = Arrays.stream(lines.split("\\s+"))
			.map(String::toUpperCase)
			.toArray(String[]::new);

        for (String s : result) {
            System.out.println(s);
        }

    }

} 

输出

 I
LOVE
JAVA
8
STREAM! 

2.IntStream -> Integer[]或 int[]

2.1 流向Integer[]

StreamInt1.java

 package com.mkyong;

import java.util.Arrays;

public class StreamInt1 {

    public static void main(String[] args) {

        int[] num = {1, 2, 3, 4, 5};

        Integer[] result = Arrays.stream(num)
			.map(x -> x * 2)
			.boxed()
			.toArray(Integer[]::new);

        System.out.println(Arrays.asList(result));

    }

} 

输出

 [2, 4, 6, 8, 10] 

2.2 流至int[]

StreamInt2.java

 package com.mkyong;

import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class StreamInt2 {

    public static void main(String[] args) {

        // IntStream -> int[]
        int[] stream1 = IntStream.rangeClosed(1, 5).toArray();
        System.out.println(Arrays.toString(stream1));

        // Stream<Integer> -> int[]
        Stream<Integer> stream2 = Stream.of(1, 2, 3, 4, 5);
        int[] result = stream2.mapToInt(x -> x).toArray();

        System.out.println(Arrays.toString(result));

    }

} 

输出

 [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5] 

参考

Tags : array java 8 stream

Java 8–如何将 IntStream 转换为 int 或 int[]

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-how-to-convert-intstream-to-int-or-int/

从一个IntStream中获取一个原语int的几个 Java 8 例子。

1.IntStream -> int

Java8Example1.java

 package com.mkyong;

import java.util.Arrays;
import java.util.OptionalInt;
import java.util.stream.IntStream;

public class Java8Example1 {

    public static void main(String[] args) {

        int[] num = {1, 2, 3, 4, 5};

        //1\. int[] -> IntStream
        IntStream stream = Arrays.stream(num);

        // 2\. OptionalInt
        OptionalInt first = stream.findFirst();

        // 3\. getAsInt()
        int result = first.getAsInt();

        System.out.println(result);                                     // 1

        // one line
        System.out.println(Arrays.stream(num).findFirst().getAsInt());  // 1

    }

} 

输出

 1
1 

Java8Example2.java

 package com.mkyong;

import java.util.Arrays;
import java.util.OptionalInt;
import java.util.stream.IntStream;

public class Java8Example2 {

    public static void main(String[] args) {

        int[] num = {1, 2, 3, 4, 5};

        //1\. int[] -> IntStream
        IntStream stream = Arrays.stream(num);

        // 2\. OptionalInt
        OptionalInt any = stream.filter(x -> x % 2 == 0).findAny();

        // 3\. getAsInt()
        int result = any.getAsInt();

        System.out.println(result); // 2 or 4

    }

} 

输出

 2 or 4 

2.IntStream -> int[]或 Integer[]

Java8Example3.java

 package com.mkyong;

import java.util.Arrays;
import java.util.stream.IntStream;

public class Java8Example3 {

    public static void main(String[] args) {

        int[] num = {1, 2, 3, 4, 5};

        IntStream stream = Arrays.stream(num);

        // IntStream -> int[]
        int[] ints = stream.toArray();

        IntStream stream2 = Arrays.stream(num);

        // IntStream -> Integer[]
        Integer[] integers = stream2.boxed().toArray(Integer[]::new);

    }

} 

参考

Java 8–如何将 IntStream 转换为 Integer[]

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-how-to-convert-intstream-to-integer/

关键是boxed()IntStream转换成Stream<Integer>,然后只转换成一个数组。

StreamExample.java

 package com.mkyong;

import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class StreamExample {

    public static void main(String[] args) {

        //int[] -> IntStream -> Stream<Integer> -> Integer[]
        int[] num = {3, 4, 5};

        //1\. int[] -> IntStream
        IntStream stream = Arrays.stream(num);

        //2\. IntStream -> Stream<Integer>
        Stream<Integer> boxed = stream.boxed();

        //3\. Stream<Integer> -> Integer[]
        Integer[] result = boxed.toArray(Integer[]::new);

        System.out.println(Arrays.toString(result));

        // one line
        Integer[] oneLineResult = Arrays.stream(num).boxed().toArray(Integer[]::new);
        System.out.println(Arrays.toString(oneLineResult));
    }

} 

输出

 [3, 4, 5]
[3, 4, 5] 

参考

Tags : array intstream java 8 stream

Java 8–如何格式化本地日期时间

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-how-to-format-localdatetime/

几个例子向你展示如何在 Java 8 中格式化java.time.LocalDateTime

1. LocalDateTime + DateTimeFormatter

要格式化 LocalDateTime 对象,使用DateTimeFormatter

TestDate1.java

 package com.mkyong.time;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class TestDate1 {
    public static void main(String[] args) {

        //Get current date time
        LocalDateTime now = LocalDateTime.now();

        System.out.println("Before : " + now);

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        String formatDateTime = now.format(formatter);

        System.out.println("After : " + formatDateTime);

    }
} 

输出

 Before : 2016-11-09T11:44:44.797

After  : 2016-11-09 11:44:44 

2.字符串-> LocalDateTime

另一个将字符串转换为LocalDateTime的例子

TestDate2.java

 package com.mkyong.time;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class TestDate2 {
    public static void main(String[] args) {

        String now = "2016-11-09 10:30";

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");

        LocalDateTime formatDateTime = LocalDateTime.parse(now, formatter);

        System.out.println("Before : " + now);

        System.out.println("After : " + formatDateTime);

        System.out.println("After : " + formatDateTime.format(formatter));

    }
} 

输出

 Before : 2016-11-09 10:30

After : 2016-11-09T10:30

After : 2016-11-09 10:30 

参考

  1. DateTimeFormatter JavaDoc
  2. Java 8–如何将字符串转换为本地日期

Java 8–如何解析带有“DD MMM”(02 Jan)的日期,而不带年份?

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-how-to-parse-date-with-dd-mmm-02-jan-without-year/

这个例子展示了如何解析一个没有指定年份的日期(02 Jan)。

JavaDateExample.java

 package com.mkyong.time;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class JavaDateExample {

    public static void main(String[] args) {

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd MMM", Locale.US);

        String date = "02 Jan";

        LocalDate localDate = LocalDate.parse(date, formatter);

        System.out.println(localDate);

        System.out.println(formatter.format(localDate));

    }

} 

输出

 Exception in thread "main" java.time.format.DateTimeParseException: Text '02 Jan' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {DayOfMonth=2, MonthOfYear=1},ISO of type java.time.format.Parsed
	at java.base/java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:2017)
	at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1952)
	at java.base/java.time.LocalDate.parse(LocalDate.java:428)
	at com.mkyong.time.JavaDateExample.main(JavaDateExample.java:20)
Caused by: java.time.DateTimeException: Unable to obtain LocalDate from TemporalAccessor: {DayOfMonth=2, MonthOfYear=1},ISO of type java.time.format.Parsed
	at java.base/java.time.LocalDate.from(LocalDate.java:396)
	at java.base/java.time.format.Parsed.query(Parsed.java:235)
	at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
	... 2 more 

解决办法

格局dd MMM不够;我们需要一个DateTimeFormatterBuilder来为日期解析提供默认年份。

JavaDateExample.java

 package com.mkyong.time;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.Locale;

public class JavaDateExample {

    public static void main(String[] args) {

        DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                .appendPattern("dd MMM")
                .parseDefaulting(ChronoField.YEAR, 2020)
                .toFormatter(Locale.US);

        String date = "02 Jan";

        LocalDate localDate = LocalDate.parse(date, formatter);

        System.out.println(localDate);

        System.out.println(formatter.format(localDate));

    }

} 

输出

 2020-01-02
02 Jan 

参考

Java 8–如何对地图进行排序

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-how-to-sort-a-map/

sorting

Java 8 Stream示例按照键或值对一个Map进行排序。

1.快速解释

Java 8 中对地图进行排序的步骤。

  1. 将地图转换成河流
  2. 分类吧
  3. 收集并返回新的LinkedHashMap(保持顺序)
 Map result = map.entrySet().stream()
	.sorted(Map.Entry.comparingByKey()) 			
	.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
	(oldValue, newValue) -> oldValue, LinkedHashMap::new)); 

P.S 默认情况下,Collectors.toMap会返回一个HashMap

2.按关键字排序

SortByKeyExample.java

 package com.mkyong.test;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class SortByKeyExample {

    public static void main(String[] argv) {

        Map<String, Integer> unsortMap = new HashMap<>();
        unsortMap.put("z", 10);
        unsortMap.put("b", 5);
        unsortMap.put("a", 6);
        unsortMap.put("c", 20);
        unsortMap.put("d", 1);
        unsortMap.put("e", 7);
        unsortMap.put("y", 8);
        unsortMap.put("n", 99);
        unsortMap.put("g", 50);
        unsortMap.put("m", 2);
        unsortMap.put("f", 9);

        System.out.println("Original...");
        System.out.println(unsortMap);

        // sort by keys, a,b,c..., and return a new LinkedHashMap
        // toMap() will returns HashMap by default, we need LinkedHashMap to keep the order.
        Map<String, Integer> result = unsortMap.entrySet().stream()
                .sorted(Map.Entry.comparingByKey())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                        (oldValue, newValue) -> oldValue, LinkedHashMap::new));

        // Not Recommend, but it works.
        //Alternative way to sort a Map by keys, and put it into the "result" map
        Map<String, Integer> result2 = new LinkedHashMap<>();
        unsortMap.entrySet().stream()
                .sorted(Map.Entry.comparingByKey())
                .forEachOrdered(x -> result2.put(x.getKey(), x.getValue()));

        System.out.println("Sorted...");
        System.out.println(result);
        System.out.println(result2);

    }

} 

输出

 Original...
{a=6, b=5, c=20, d=1, e=7, f=9, g=50, y=8, z=10, m=2, n=99}

Sorted...
{a=6, b=5, c=20, d=1, e=7, f=9, g=50, m=2, n=99, y=8, z=10}
{a=6, b=5, c=20, d=1, e=7, f=9, g=50, m=2, n=99, y=8, z=10} 

3.按值排序

SortByValueExample.java

 package com.mkyong.test;

package com.mkyong;

import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class SortByValueExample {

    public static void main(String[] argv) {

        Map<String, Integer> unsortMap = new HashMap<>();
        unsortMap.put("z", 10);
        unsortMap.put("b", 5);
        unsortMap.put("a", 6);
        unsortMap.put("c", 20);
        unsortMap.put("d", 1);
        unsortMap.put("e", 7);
        unsortMap.put("y", 8);
        unsortMap.put("n", 99);
        unsortMap.put("g", 50);
        unsortMap.put("m", 2);
        unsortMap.put("f", 9);

        System.out.println("Original...");
        System.out.println(unsortMap);

        //sort by values, and reserve it, 10,9,8,7,6...
        Map<String, Integer> result = unsortMap.entrySet().stream()
                .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                        (oldValue, newValue) -> oldValue, LinkedHashMap::new));

        //Alternative way
        Map<String, Integer> result2 = new LinkedHashMap<>();
        unsortMap.entrySet().stream()
                .sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
                .forEachOrdered(x -> result2.put(x.getKey(), x.getValue()));

        System.out.println("Sorted...");
        System.out.println(result);
        System.out.println(result2);

    }
} 

输出

 Original...
{a=6, b=5, c=20, d=1, e=7, f=9, g=50, y=8, z=10, m=2, n=99}

Sorted...
{n=99, g=50, c=20, z=10, f=9, y=8, e=7, a=6, b=5, m=2, d=1}
{n=99, g=50, c=20, z=10, f=9, y=8, e=7, a=6, b=5, m=2, d=1} 

4.地图

Java 8–如何使用 stream.sorted()对列表进行排序

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-how-to-sort-list-with-stream-sorted/

几个例子告诉你如何用stream.sorted()List排序

1.目录

1.1 用Comparator.naturalOrder()对列表进行排序

 package com.mkyong.sorted;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamApplication {

    public static void main(String[] args) {

        List<String> list = Arrays.asList("9", "A", "Z", "1", "B", "Y", "4", "a", "c");

        /* 
		List<String> sortedList = list.stream()
			.sorted(Comparator.naturalOrder())
			.collect(Collectors.toList());

        List<String> sortedList = list.stream()
			.sorted((o1,o2)-> o1.compareTo(o2))
			.collect(Collectors.toList());
		*/

		List<String> sortedList = list.stream().sorted().collect(Collectors.toList());

        sortedList.forEach(System.out::println);

    }
} 

输出

 1
4
9
A
B
Y
Z
a
c 

1.2 用Comparator.reverseOrder()对列表进行排序

 package com.mkyong.sorted;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class StreamApplication {

    public static void main(String[] args) {

        List<String> list = Arrays.asList("9", "A", "Z", "1", "B", "Y", "4", "a", "c");

        /*
		List<String> sortedList = list.stream()
			.sorted((o1,o2)-> o2.compareTo(o1))
			.collect(Collectors.toList());
		*/

        List<String> sortedList = list.stream()
			.sorted(Comparator.reverseOrder())
			.collect(Collectors.toList());

        sortedList.forEach(System.out::println);

    }
} 

输出

 c
a
Z
Y
B
A
9
4
1 

2.列出对象

1.1 按年龄排序,自然顺序。

 package com.mkyong.sorted;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class StreamApplication {

    static List<User> users = Arrays.asList(
            new User("C", 30),
            new User("D", 40),
            new User("A", 10),
            new User("B", 20),
            new User("E", 50));

    public static void main(String[] args) {

        /*List<User> sortedList = users.stream()
			.sorted((o1, o2) -> o1.getAge() - o2.getAge())
			.collect(Collectors.toList());*/

        List<User> sortedList = users.stream()
			.sorted(Comparator.comparingInt(User::getAge))
			.collect(Collectors.toList());

        sortedList.forEach(System.out::println);

    }

    static class User {

        private String name;
        private int age;

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

        public String getName() {
            return name;
        }

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

        public int getAge() {
            return age;
        }

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

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

输出

 User{name='A', age=10}
User{name='B', age=20}
User{name='C', age=30}
User{name='D', age=40}
User{name='E', age=50} 

1.2 逆序。

 List<User> sortedList = users.stream()
		.sorted(Comparator.comparingInt(User::getAge)
		.reversed())
		.collect(Collectors.toList());

    sortedList.forEach(System.out::println); 

输出

 User{name='E', age=50}
User{name='D', age=40}
User{name='C', age=30}
User{name='B', age=20}
User{name='A', age=10} 

1.3 按名称排序

 /*List<User> sortedList = users.stream()
		.sorted((o1, o2) -> o1.getName().compareTo(o2.getName()))
		.collect(Collectors.toList());*/

	List<User> sortedList = users.stream()
		.sorted(Comparator.comparing(User::getName))
		.collect(Collectors.toList()); 

参考

Java 8–如何使用 Stream 对 BigDecimal 求和?

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-how-to-sum-bigdecimal-using-stream/

在 Java 8 中,我们可以使用Stream.reduce()对一列BigDecimal求和。

1.Stream.reduce()

使用一个普通的 for 循环和一个stream.reduce()对一系列BigDecimal值求和的 Java 示例。

JavaBigDecimal.java

 package com.mkyong;

import java.math.BigDecimal;
import java.util.LinkedList;
import java.util.List;

public class JavaBigDecimal {

    public static void main(String[] args) {

        List<BigDecimal> invoices = new LinkedList<>();
        invoices.add(BigDecimal.valueOf(9.9));
        invoices.add(BigDecimal.valueOf(1.0));
        invoices.add(BigDecimal.valueOf(19.99));
        invoices.add(BigDecimal.valueOf(0.2));
        invoices.add(BigDecimal.valueOf(5.5));

        // sum using a for loop
        BigDecimal sum = BigDecimal.ZERO;
        for (BigDecimal amt : invoices) {
            sum = sum.add(amt);
        }
        System.out.println("Sum = " + sum);

        // sum using stream
        BigDecimal sum2 = invoices.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        System.out.println("Sum (Stream) = " + sum2);

    }

} 

输出

 Sum = 36.59
Sum (Stream) = 36.59 

2.映射和缩小

对列表Invoices中的所有BigDecimal求和。

JavaBigDecimalObject.java

 package com.mkyong;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.List;

public class JavaBigDecimalObject {

    public static void main(String[] args) {

        List<Invoice> invoices = Arrays.asList(
                new Invoice("I1001", BigDecimal.valueOf(9.99), BigDecimal.valueOf(1)),
                new Invoice("I1002", BigDecimal.valueOf(19.99), BigDecimal.valueOf(1.5)),
                new Invoice("I1003", BigDecimal.valueOf(4.888), BigDecimal.valueOf(2)),
                new Invoice("I1004", BigDecimal.valueOf(4.99), BigDecimal.valueOf(5)),
                new Invoice("I1005", BigDecimal.valueOf(.5), BigDecimal.valueOf(2.3))
        );

        BigDecimal sum = invoices.stream()
                .map(x -> x.getQty().multiply(x.getPrice()))    // map
                .reduce(BigDecimal.ZERO, BigDecimal::add);      // reduce

        System.out.println(sum);    // 75.851
        System.out.println(sum.setScale(2, RoundingMode.HALF_UP));  // 75.85

    }

}

class Invoice {

    String invoiceNo;
    BigDecimal price;
    BigDecimal qty;

    public Invoice(String invoiceNo, BigDecimal price, BigDecimal qty) {
        this.invoiceNo = invoiceNo;
        this.price = price;
        this.qty = qty;
    }

    public String getInvoiceNo() {
        return invoiceNo;
    }

    public void setInvoiceNo(String invoiceNo) {
        this.invoiceNo = invoiceNo;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public BigDecimal getQty() {
        return qty;
    }

    public void setQty(BigDecimal qty) {
        this.qty = qty;
    }
} 

输出

 75.851
75.85 

参考

Java 8 Lambda:比较器示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-lambda-comparator-example/

java-lambda-expression

在本例中,我们将向您展示如何使用 Java 8 Lambda 表达式编写一个Comparator来对列表进行排序。

1.经典Comparator例子。

 Comparator<Developer> byName = new Comparator<Developer>() {
		@Override
		public int compare(Developer o1, Developer o2) {
			return o1.getName().compareTo(o2.getName());
		}
	}; 

2.Lambda 表达式等价。

 Comparator<Developer> byName = 
		(Developer o1, Developer o2)->o1.getName().compareTo(o2.getName()); 

1.不使用 Lambda 排序

使用年龄比较Developer对象的示例。通常,您使用Collections.sort并像这样传递一个匿名的Comparator类:

TestSorting.java

 package com.mkyong.java8;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class TestSorting {

	public static void main(String[] args) {

		List<Developer> listDevs = getDevelopers();

		System.out.println("Before Sort");
		for (Developer developer : listDevs) {
			System.out.println(developer);
		}

		//sort by age
		Collections.sort(listDevs, new Comparator<Developer>() {
			@Override
			public int compare(Developer o1, Developer o2) {
				return o1.getAge() - o2.getAge();
			}
		});

		System.out.println("After Sort");
		for (Developer developer : listDevs) {
			System.out.println(developer);
		}

	}

	private static List<Developer> getDevelopers() {

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

		result.add(new Developer("mkyong", new BigDecimal("70000"), 33));
		result.add(new Developer("alvin", new BigDecimal("80000"), 20));
		result.add(new Developer("jason", new BigDecimal("100000"), 10));
		result.add(new Developer("iris", new BigDecimal("170000"), 55));

		return result;

	}

} 

输出

 Before Sort
Developer [name=mkyong, salary=70000, age=33]
Developer [name=alvin, salary=80000, age=20]
Developer [name=jason, salary=100000, age=10]
Developer [name=iris, salary=170000, age=55]

After Sort
Developer [name=jason, salary=100000, age=10]
Developer [name=alvin, salary=80000, age=20]
Developer [name=mkyong, salary=70000, age=33]
Developer [name=iris, salary=170000, age=55] 

当排序需求改变时,您只需传入另一个新的匿名Comparator类:

 //sort by age
	Collections.sort(listDevs, new Comparator<Developer>() {
		@Override
		public int compare(Developer o1, Developer o2) {
			return o1.getAge() - o2.getAge();
		}
	});

	//sort by name	
	Collections.sort(listDevs, new Comparator<Developer>() {
		@Override
		public int compare(Developer o1, Developer o2) {
			return o1.getName().compareTo(o2.getName());
		}
	});

	//sort by salary
	Collections.sort(listDevs, new Comparator<Developer>() {
		@Override
		public int compare(Developer o1, Developer o2) {
			return o1.getSalary().compareTo(o2.getSalary());
		}
	}); 

它可以工作,但是,你是否认为仅仅因为你想改变一行代码就创建一个类有点奇怪?

2.用 Lambda 排序

在 Java 8 中,List接口直接支持sort方法,不再需要使用Collections.sort

 //List.sort() since Java 8
	listDevs.sort(new Comparator<Developer>() {
		@Override
		public int compare(Developer o1, Developer o2) {
			return o2.getAge() - o1.getAge();
		}
	}); 

Lambda 表达式示例:

TestSorting.java

 package com.mkyong.java8;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class TestSorting {

	public static void main(String[] args) {

		List<Developer> listDevs = getDevelopers();

		System.out.println("Before Sort");
		for (Developer developer : listDevs) {
			System.out.println(developer);
		}

		System.out.println("After Sort");

		//lambda here!
		listDevs.sort((Developer o1, Developer o2)->o1.getAge()-o2.getAge());

		//java 8 only, lambda also, to print the List
		listDevs.forEach((developer)->System.out.println(developer));
	}

	private static List<Developer> getDevelopers() {

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

		result.add(new Developer("mkyong", new BigDecimal("70000"), 33));
		result.add(new Developer("alvin", new BigDecimal("80000"), 20));
		result.add(new Developer("jason", new BigDecimal("100000"), 10));
		result.add(new Developer("iris", new BigDecimal("170000"), 55));

		return result;

	}

} 

输出

 Before Sort
Developer [name=mkyong, salary=70000, age=33]
Developer [name=alvin, salary=80000, age=20]
Developer [name=jason, salary=100000, age=10]
Developer [name=iris, salary=170000, age=55]

After Sort
Developer [name=jason, salary=100000, age=10]
Developer [name=alvin, salary=80000, age=20]
Developer [name=mkyong, salary=70000, age=33]
Developer [name=iris, salary=170000, age=55] 

3.更多 Lambda 示例

3.1 按年龄排序

 //sort by age
	Collections.sort(listDevs, new Comparator<Developer>() {
		@Override
		public int compare(Developer o1, Developer o2) {
			return o1.getAge() - o2.getAge();
		}
	});

	//lambda
	listDevs.sort((Developer o1, Developer o2)->o1.getAge()-o2.getAge());

	//lambda, valid, parameter type is optional
	listDevs.sort((o1, o2)->o1.getAge()-o2.getAge()); 

3.2 按名称排序

 //sort by name
	Collections.sort(listDevs, new Comparator<Developer>() {
		@Override
		public int compare(Developer o1, Developer o2) {
			return o1.getName().compareTo(o2.getName());
		}
	});

	//lambda
	listDevs.sort((Developer o1, Developer o2)->o1.getName().compareTo(o2.getName()));		

	//lambda
	listDevs.sort((o1, o2)->o1.getName().compareTo(o2.getName())); 

3.3 按薪资排序

 //sort by salary
	Collections.sort(listDevs, new Comparator<Developer>() {
		@Override
		public int compare(Developer o1, Developer o2) {
			return o1.getSalary().compareTo(o2.getSalary());
		}
	});				

	//lambda
	listDevs.sort((Developer o1, Developer o2)->o1.getSalary().compareTo(o2.getSalary()));

	//lambda
	listDevs.sort((o1, o2)->o1.getSalary().compareTo(o2.getSalary())); 

3.4 反向排序。

3.4.1 Lambda 表达式使用工资对列表进行排序。

 Comparator<Developer> salaryComparator = (o1, o2)->o1.getSalary().compareTo(o2.getSalary());
	listDevs.sort(salaryComparator); 

输出

 Developer [name=mkyong, salary=70000, age=33]
Developer [name=alvin, salary=80000, age=20]
Developer [name=jason, salary=100000, age=10]
Developer [name=iris, salary=170000, age=55] 

3.4.2 Lambda 表达式使用工资对列表进行排序,顺序相反。

 Comparator<Developer> salaryComparator = (o1, o2)->o1.getSalary().compareTo(o2.getSalary());
	listDevs.sort(salaryComparator.reversed()); 

输出

 Developer [name=iris, salary=170000, age=55]
Developer [name=jason, salary=100000, age=10]
Developer [name=alvin, salary=80000, age=20]
Developer [name=mkyong, salary=70000, age=33] 

参考

  1. 开始使用 Java Lambda 表达式
  2. 甲骨文:λ表达式
  3. 甲骨文:比较器

Tags : comparator java8 lambda sorting

Java 8 方法引用,双冒号(::)运算符

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-method-references-double-colon-operator/

在 Java 8 中,双冒号(::)操作符被称为方法引用。参考下面的例子:

打印列表的匿名类。

 List<String> list = Arrays.asList("node", "java", "python", "ruby");
list.forEach(new Consumer<String>() {       // anonymous class
    @Override
    public void accept(String str) {
        System.out.println(str);
    }
}); 

匿名类-> Lambda 表达式。

 List<String> list = Arrays.asList("node", "java", "python", "ruby");
list.forEach(str -> System.out.println(str)); // lambda 

Lambda 表达式->方法引用。

 List<String> list = Arrays.asList("node", "java", "python", "ruby");
list.forEach(System.out::println);          // method references 

匿名类->λ表达式- >方法引用

注意
lambda 表达式或方法引用什么都不做,只是对现有方法的另一种方式调用。通过方法引用,它获得了更好的可读性。

有四种方法引用:

  • 对静态方法的引用ClassName::staticMethodName
  • 引用特定对象的实例方法Object::instanceMethodName
  • 引用特定类型的任意对象的实例方法ContainingType::methodName
  • 对构造函数的引用ClassName::new

1.静态法

λ表达式。

 (args) -> ClassName.staticMethodName(args) 

方法参考。

 ClassName::staticMethodName 

1.1 这个例子打印一个字符串列表,方法引用一个静态方法SimplePrinter::print

Java8MethodReference1a.java

 package com.mkyong;

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class Java8MethodReference1a {

    public static void main(String[] args) {

        List<String> list = Arrays.asList("A", "B", "C");

        // anonymous class
        list.forEach(new Consumer<String>() {
            @Override
            public void accept(String x) {
                SimplePrinter.print(x);
            }
        });

        // lambda expression
        list.forEach(x -> SimplePrinter.print(x));

        // method reference
        list.forEach(SimplePrinter::print);

    }

}

class SimplePrinter {
    public static void print(String str) {
        System.out.println(str);
    }
} 

1.2 这个例子将一个字符串列表转换成一个整数列表,方法引用一个静态方法Integer::parseInt

Integer.java

 public static int parseInt(String s) throws NumberFormatException {
        return parseInt(s,10);
  } 

Java8MethodReference1b.java

 package com.mkyong;

import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Java8MethodReference1b {

    public static void main(String[] args) {

        List<String> list = Arrays.asList("1", "2", "3");

        // anonymous class
        List<Integer> collect1 = list.stream()
                .map(new Function<String, Integer>() {
                    @Override
                    public Integer apply(String s) {
                        return Integer.parseInt(s);
                    }
                })
                .collect(Collectors.toList());

        // lambda expression
        List<Integer> collect2 = list.stream()
                .map(s -> Integer.parseInt(s))
                .collect(Collectors.toList());

        // method reference
        List<Integer> collect3 = list.stream()
                .map(Integer::parseInt)
                .collect(Collectors.toList());

    }

} 

1.3 此示例连接两个Integer并返回一个String。它将方法引用静态方法IntegerUtils::join作为参数传递给另一个接受BiFunction的方法。

Java8MethodReference1c.java

 package com.mkyong;

import java.util.function.BiFunction;

public class Java8MethodReference1c {

    public static void main(String[] args) {

        // anonymous class
        String result1 = playTwoArgument(1, 2, new BiFunction<Integer, Integer, String>() {
                  @Override
                  public String apply(Integer a, Integer b) {
                      return IntegerUtils.join(a, b);
                  }
              });                                                                   // 3

        // lambda
        String result1 = playTwoArgument(1, 2, (a, b) -> IntegerUtils.join(a, b));  // 3

        // method reference
        String result2 = playTwoArgument(1, 2, IntegerUtils::join);                 // 3

    }

    private static <R> R playTwoArgument(Integer i1, Integer i2,
        BiFunction<Integer, Integer, R> func) {
        return func.apply(i1, i2);
    }

}

class IntegerUtils{

    public static String join(Integer a, Integer b) {
        return String.valueOf(a + b);
    }

} 

2.对特定对象的实例方法的引用

λ表达式。

 (args) -> object.instanceMethodName(args) 

方法参考。

 object::instanceMethodName 

2.1 这个例子按照薪水对一个Employee列表进行排序。我们可以引用一个特定对象ComparatorProvider的实例方法compareBySalary

Java8MethodReference2

 package com.mkyong;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;

public class Java8MethodReference2 {

    public static void main(String[] args) {

        List<Employee> list = Arrays.asList(
                new Employee("mkyong", 38, BigDecimal.valueOf(3800)),
                new Employee("zilap", 5, BigDecimal.valueOf(100)),
                new Employee("ali", 25, BigDecimal.valueOf(2500)),
                new Employee("unknown", 99, BigDecimal.valueOf(9999)));

        // anonymous class
        /*list.sort(new Comparator<Employee>() {
            @Override
            public int compare(Employee o1, Employee o2) {
                return provider.compareBySalary(o1, o2);
            }
        });*/

        ComparatorProvider provider = new ComparatorProvider();

        // lambda
        // list.sort((o1, o2) -> provider.compareBySalary(o1, o2));

        // method reference
        list.sort(provider::compareBySalary);

        list.forEach(x -> System.out.println(x));

    }

}

class ComparatorProvider {

    public int compareByAge(Employee o1, Employee o2) {
        return o1.getAge().compareTo(o2.getAge());
    }

    public int compareByName(Employee o1, Employee o2) {
        return o1.getName().compareTo(o2.getName());
    }

    public int compareBySalary(Employee o1, Employee o2) {
        return o1.getAge().compareTo(o2.getAge());
    }

} 

Employee.java

 package com.mkyong;

import java.math.BigDecimal;

public class Employee {

    String name;
    Integer age;
    BigDecimal salary;

    // generated by IDE, getters, setters, constructor, toString
} 

输出

 Employee{name='zilap', age=5, salary=100}
Employee{name='ali', age=25, salary=2500}
Employee{name='mkyong', age=38, salary=3800}
Employee{name='unknown', age=99, salary=9999} 

3.对特定类型的任意对象的实例方法的引用。

这种说法有点混乱,不需要什么解释,请看下面的例子:

λ表达式。

 // arg0 is the first argument
(arg0, rest_of_args) -> arg0.methodName(rest_of_args)

// example, assume a and b are String
(a, b) -> a.compareToIgnoreCase(b) 

方法参考。

 // first argument type
arg0_Type::methodName

// arg0 is type of ClassName
ClassName::methodName

// example, a is type of String
String::compareToIgnoreCase 

对于(String a, String b),其中ab为任意名称,String为其任意类型。这个例子使用了对特定类型String的任意对象a(第一个参数)的实例方法compareToIgnoreCase的方法引用。

3.1 查看本方法参考中的正式示例

 String[] stringArray = { "Barbara", "James", "Mary", "John",
                "Patricia", "Robert", "Michael", "Linda" };
  Arrays.sort(stringArray, String::compareToIgnoreCase); 

我们传递了一个方法引用String::compareToIgnoreCase作为Arrays.sort的比较器。

讲解
复习Arrays.sort方法签名:

 public static <T> void sort(T[] a, Comparator<? super T> c) {
} 

在上面的例子中,Arrays.sort期望一个Comparator<String>Comparator是一个函数接口,它的抽象方法compare匹配BiFunction<String, String, Integer>,它带两个参数String并返回一个int

Comparator.java

 @FunctionalInterface
public interface Comparator<T> {
    int compare(T o1, T o2);  // this matches BiFunction<String, String, Integer>
} 

查看BiFunction方法签名:

BiFunction.java

 @FunctionalInterface
public interface BiFunction<T, U, R> {
      R apply(T t, U u);
} 

延伸阅读——Java 8 双函数示例

below lambda 为BiFunction<String,String,Integer>提供了实现,因此Arrays.sort接受 below lambda 表达式作为有效语法。

 (String a, String b) -> a.compareToIgnoreCase(b) // return int

// a is type of String
// method reference
String::compareToIgnoreCase 

3.2 让我们看另一个例子。

Java8MethodReference3a.java

 package com.mkyong;

import java.util.function.BiPredicate;
import java.util.function.Function;

public class Java8MethodReference3a {

    public static void main(String[] args) {

        // lambda
        int result = playOneArgument("mkyong", x -> x.length());   // 6

        // method reference
        int result2 = playOneArgument("mkyong", String::length);   // 6

        // lambda
        Boolean result3 = playTwoArgument("mkyong", "y", (a, b) -> a.contains(b)); // true

        // method reference
        Boolean result4 = playTwoArgument("mkyong", "y", String::contains);        // true

        // lambda
        Boolean result5 = playTwoArgument("mkyong", "1", (a, b) -> a.startsWith(b)); // false

        // method reference
        Boolean result6 = playTwoArgument("mkyong", "y", String::startsWith);        // false

        System.out.println(result6);
    }

    static <R> R playOneArgument(String s1, Function<String, R> func) {
        return func.apply(s1);
    }

    static Boolean playTwoArgument(String s1, String s2, BiPredicate<String, String> func) {
        return func.test(s1, s2);
    }

} 

3.3 让我们看另一个例子,自定义对象。

Java8MethodReference3b.java

 package com.mkyong;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.function.BiFunction;

public class Java8MethodReference3b {

    public static void main(String[] args) {

        Invoice obj = new Invoice("A001", BigDecimal.valueOf(1.99), 3);

        InvoiceCalculator formula = new InvoiceCalculator();

        // lambda
        BigDecimal result = calculate(formula, obj, (f, o) -> f.normal(o));         // 5.97

        // method reference
        BigDecimal result2 = calculate(formula, obj, InvoiceCalculator::normal);    // 5.97

        // lambda
        BigDecimal result3 = calculate(formula, obj, (f, o) -> f.promotion(o));     // 5.37

        // method reference
        BigDecimal result4 = calculate(formula, obj, InvoiceCalculator::promotion); // 5.37

    }

    static BigDecimal calculate(InvoiceCalculator formula, Invoice s1,
                                BiFunction<InvoiceCalculator, Invoice, BigDecimal> func) {
        return func.apply(formula, s1);
    }

}

class InvoiceCalculator {

    public BigDecimal normal(Invoice obj) {
        return obj.getUnitPrice().multiply(BigDecimal.valueOf(obj.qty));
    }

    public BigDecimal promotion(Invoice obj) {
        return obj.getUnitPrice()
                .multiply(BigDecimal.valueOf(obj.qty))
                .multiply(BigDecimal.valueOf(0.9))
                .setScale(2, RoundingMode.HALF_UP);
    }
}

class Invoice {

    String no;
    BigDecimal unitPrice;
    Integer qty;

    // generated by IDE, setters, gettes, constructor, toString
} 

第一个参数是一种类型的InvoiceCalculator。因此,我们可以引用特定类型InvoiceCalculator的任意对象f的实例方法(normal or promotion)。

 (f, o) -> f.normal(o))
(f, o) -> f.promotion(o))

InvoiceCalculator::normal
InvoiceCalculator::promotion 

明白了吗?没有更多的例子🙂

4.对构造函数的引用。

λ表达式。

 (args) -> new ClassName(args) 

方法参考。

 ClassName::new 

4.1 对默认构造函数的引用。

Java8MethodReference4a.java

 package com.mkyong;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

public class Java8MethodReference4a {

    public static void main(String[] args) {

        // lambda
        Supplier<Map> obj1 = () -> new HashMap();   // default HashMap() constructor
        Map map1 = obj1.get();

        // method reference
        Supplier<Map> obj2 = HashMap::new;
        Map map2 = obj2.get();

        // lambda
        Supplier<Invoice> obj3 = () -> new Invoice(); // default Invoice() constructor
        Invoice invoice1 = obj3.get();

        // method reference
        Supplier<Invoice> obj4 = Invoice::new;
        Invoice invoice2 = obj4.get();

    }

}

class Invoice {

    String no;
    BigDecimal unitPrice;
    Integer qty;

    public Invoice() {
    }

    //... generated by IDE
} 

4.2 对接受参数的构造函数的引用—Invoice(BigDecimal unitPrice)

Java8MethodReference4b.java

 package com.mkyong;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

public class Java8MethodReference4b {

    public static void main(String[] args) {

        List<BigDecimal> list = Arrays.asList(
                BigDecimal.valueOf(9.99),
                BigDecimal.valueOf(2.99),
                BigDecimal.valueOf(8.99));

        // lambda
        // List<Invoice> invoices = fakeInvoice(list, (price) -> new Invoice(price));

        // method reference
        List<Invoice> invoices = fakeInvoice(list, Invoice::new);

        invoices.forEach(System.out::println);
    }

    static List<Invoice> fakeInvoice(List<BigDecimal> list, Function<BigDecimal, Invoice> func) {
        List<Invoice> result = new ArrayList<>();

        for (BigDecimal amount : list) {
            result.add(func.apply(amount));
        }
        return result;
    }

}

class Invoice {

    String no;
    BigDecimal unitPrice;
    Integer qty;

    public Invoice(BigDecimal unitPrice) {
        this.unitPrice = unitPrice;
    }

    //... generated by IDE
} 

输出

 Invoice{no='null', unitPrice=9.99, qty=null}
Invoice{no='null', unitPrice=2.99, qty=null}
Invoice{no='null', unitPrice=8.99, qty=null} 

完成了。

参考

Java 8–MinguoDate 示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-minguodate-examples/

这种民国日期日历系统主要在台湾(中华民国……)使用

(ISO) 1912-01-01 = 1-01-01 (Minguo ROC)

例如,要将当前日期转换为民国日期,只需用数字 1911 减去当前年份

2016 (ISO) - 1911 = 105 (Minguo ROC)

1.LocalDate -> MinguoDate

查看完整的示例,将LocalDate转换为MinguoDate

TestMinguoDate.java

 package com.mkyong.date;

import java.time.LocalDate;
import java.time.chrono.MinguoDate;

public class TestMinguoDate {

    public static void main(String[] args) {

        // LocalDate -> MinguoDate
        System.out.println("Example 1...");        

        LocalDate localDate = LocalDate.of(1912, 1, 1);
        MinguoDate minguo = MinguoDate.from(localDate);
        System.out.println("LocalDate : " + localDate); //1912-01-01
        System.out.println("MinguoDate : " + minguo);   //1-01-01

        // MinguoDate -> LocalDate
        System.out.println("\nExample 2...");

        MinguoDate minguo2 = MinguoDate.of(105, 8, 24);
        //LocalDate localDate = LocalDate.ofEpochDay(minguo2.toEpochDay());
        LocalDate localDate2 = LocalDate.from(minguo2);
        System.out.println("MinguoDate : " + minguo2);   //105-08-24
        System.out.println("LocalDate : " + localDate2); //2016-08-24

    }

} 

输出

 Example 1...
LocalDate : 1912-01-01
MinguoDate : Minguo ROC 1-01-01

Example 2...
MinguoDate : Minguo ROC 105-08-24
LocalDate : 2016-08-24 

参考

  1. MinguoDate JavaDoc
  2. 民国历

Tags : java.time java8 minguo

Java 8 可选深度

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-optional-in-depth/

Java 8 在 java.util 包中引入了一个新的可选类。它用于表示值存在或不存在。这个新构造的主要优点是不再有太多的空检查和NullPointerException。它避免了任何运行时NullPointerExceptions,支持我们开发干净整洁的 Java APIs 或应用程序。像集合和数组一样,它也是一个最多容纳一个值的容器。让我们用一些有用的例子来探索这个新的结构。

Java 8 可选的优点:

  1. 不需要空检查。
  2. 运行时不再出现 NullPointerException。
  3. 我们可以开发干净整洁的 API。
  4. 不再有锅炉板代码

1.可选基本示例

如果给定对象中存在一个值,方法返回一个非空的可选值。否则返回空可选。

Optionaal.empty()方法对于创建一个空的可选对象很有用。

OptionalBasicExample.java

 package com.mkyong;

import java.util.Optional;

public class OptionalBasicExample {

    public static void main(String[] args) {

        Optional<String> gender = Optional.of("MALE");
        String answer1 = "Yes";
        String answer2 = null;

        System.out.println("Non-Empty Optional:" + gender);
        System.out.println("Non-Empty Optional: Gender value : " + gender.get());
        System.out.println("Empty Optional: " + Optional.empty());

        System.out.println("ofNullable on Non-Empty Optional: " + Optional.ofNullable(answer1));
        System.out.println("ofNullable on Empty Optional: " + Optional.ofNullable(answer2));

        // java.lang.NullPointerException
        System.out.println("ofNullable on Non-Empty Optional: " + Optional.of(answer2));

    }

} 

输出

 Non-Empty Optional:Optional[MALE]
Non-Empty Optional: Gender value : MALE
Empty Optional: Optional.empty

ofNullable on Non-Empty Optional: Optional[Yes]
ofNullable on Empty Optional: Optional.empty

Exception in thread "main" java.lang.NullPointerException
	at java.util.Objects.requireNonNull(Objects.java:203)
	at java.util.Optional.<init>(Optional.java:96)
	at java.util.Optional.of(Optional.java:108)
	//... 

freestar.config.enabled_slots.push({ placementName: "mkyong_incontent_1", slotId: "mkyong_incontent_1" });

2.可选。地图和平面图

OptionalMapFlapMapExample.java

 package com.mkyong;

import java.util.Optional;

public class OptionalMapFlapMapExample {

    public static void main(String[] args) {

        Optional<String> nonEmptyGender = Optional.of("male");
        Optional<String> emptyGender = Optional.empty();

        System.out.println("Non-Empty Optional:: " + nonEmptyGender.map(String::toUpperCase));
        System.out.println("Empty Optional    :: " + emptyGender.map(String::toUpperCase));

        Optional<Optional<String>> nonEmptyOtionalGender = Optional.of(Optional.of("male"));
        System.out.println("Optional value   :: " + nonEmptyOtionalGender);
        System.out.println("Optional.map     :: " + nonEmptyOtionalGender.map(gender -> gender.map(String::toUpperCase)));
        System.out.println("Optional.flatMap :: " + nonEmptyOtionalGender.flatMap(gender -> gender.map(String::toUpperCase)));

    }

} 

输出

 Non-Empty Optional:: Optional[MALE]
Empty Optional    :: Optional.empty
Optional value   :: Optional[Optional[male]]
Optional.map     :: Optional[Optional[MALE]]
Optional.flatMap :: Optional[MALE] 

3.可选.过滤器

OptionalFilterExample.java

 package com.mkyong;

import java.util.Optional;

public class OptionalFilterExample {

    public static void main(String[] args) {

        Optional<String> gender = Optional.of("MALE");
        Optional<String> emptyGender = Optional.empty();

        //Filter on Optional
        System.out.println(gender.filter(g -> g.equals("male"))); //Optional.empty
        System.out.println(gender.filter(g -> g.equalsIgnoreCase("MALE"))); //Optional[MALE]
        System.out.println(emptyGender.filter(g -> g.equalsIgnoreCase("MALE"))); //Optional.empty

    }

} 

输出

 Optional.empty
Optional[MALE]
Optional.empty 

4.可选的 isPresent 和 ifPresent

如果给定的可选对象非空,则返回 true。否则返回 false。

如果给定的可选对象非空,则执行给定的动作。否则返回 false。

OptionalIfPresentExample.java

 package com.mkyong;

import java.util.Optional;

public class OptionalIfPresentExample {

    public static void main(String[] args) {

        Optional<String> gender = Optional.of("MALE");
        Optional<String> emptyGender = Optional.empty();

        if (gender.isPresent()) {
            System.out.println("Value available.");
        } else {
            System.out.println("Value not available.");
        }

        gender.ifPresent(g -> System.out.println("In gender Option, value available."));

        //condition failed, no output print
        emptyGender.ifPresent(g -> System.out.println("In emptyGender Option, value available."));

    }

} 

输出

 Value available.
In gender Option, value available. 

5.可选或其他方法

如果存在于可选容器中,它将返回值。否则返回给定的默认值。

OptionalOrElseExample.java

 package com.mkyong;

import java.util.Optional;

public class OptionalOrElseExample {

    public static void main(String[] args) {

        Optional<String> gender = Optional.of("MALE");
        Optional<String> emptyGender = Optional.empty();

        System.out.println(gender.orElse("<N/A>")); //MALE
        System.out.println(emptyGender.orElse("<N/A>")); //<N/A>

        System.out.println(gender.orElseGet(() -> "<N/A>")); //MALE
        System.out.println(emptyGender.orElseGet(() -> "<N/A>")); //<N/A>

    }

} 

输出

 MALE
<N/A>
MALE
<N/A> 

6.不带 Java 8 可选

正如大家对网上购物所熟悉的那样。让我们假设我们想要为一个著名的电子商务网站实现一个移动产品模块。

让我们在没有 Java 8 可选的情况下实现移动域模块。

ScreenResolution.java

 package com.mkyong.without.optional;

public class ScreenResolution {

	private int width;
	private int height;

	public ScreenResolution(int width, int height){
		this.width = width;
		this.height = height;
	}

	public int getWidth() {
		return width;
	}

	public int getHeight() {
		return height;
	}

} 

DisplayFeatures.java

 package com.mkyong.without.optional;

public class DisplayFeatures {

	private String size; // In inches
	private ScreenResolution resolution;

	public DisplayFeatures(String size, ScreenResolution resolution){
		this.size = size;
		this.resolution = resolution;
	}

	public String getSize() {
		return size;
	}
	public ScreenResolution getResolution() {
		return resolution;
	}

} 

Mobile.java

 package com.mkyong.without.optional;

public class Mobile {

	private long id;
	private String brand;
	private String name;
	private DisplayFeatures displayFeatures;
	// Likewise we can see Memory Features, Camera Features etc.

	public Mobile(long id, String brand, String name, 
                            DisplayFeatures displayFeatures){
		this.id = id;
		this.brand = brand;
		this.name = name;
		this.displayFeatures = displayFeatures;
	}

	public long getId() {
		return id;
	}

	public String getBrand() {
		return brand;
	}

	public String getName() {
		return name;
	}

	public DisplayFeatures getDisplayFeatures() {
		return displayFeatures;
	}

} 

在这里,如果我们观察getMobileScreenWidth()方法,它有许多锅炉板代码和许多空检查。在 Java 8 之前,我们应该做所有这些无意义的事情来避免运行时 NullPointerExceptions。

MobileService.java

 package com.mkyong.without.optional;

public class MobileService {

	public int getMobileScreenWidth(Mobile mobile){

		if(mobile != null){
			DisplayFeatures dfeatures = mobile.getDisplayFeatures();
			if(dfeatures != null){
				ScreenResolution resolution = dfeatures.getResolution();
				if(resolution != null){
					return resolution.getWidth();
				}
			}
		}
		return 0;

	}

} 

开发一个测试应用程序来测试这些领域对象。

MobileTesterWithoutOptional.java

 package com.mkyong.without.optional;

public class MobileTesterWithoutOptional {

	public static void main(String[] args) {

		ScreenResolution resolution = new ScreenResolution(750,1334);
		DisplayFeatures dfeatures = new DisplayFeatures("4.7", resolution);
		Mobile mobile = new Mobile(2015001, "Apple", "iPhone 6s", dfeatures);

		MobileService mService = new MobileService();

		int mobileWidth = mService.getMobileScreenWidth(mobile);
		System.out.println("Apple iPhone 6s Screen Width = " + mobileWidth);

		ScreenResolution resolution2 = new ScreenResolution(0,0);
		DisplayFeatures dfeatures2 = new DisplayFeatures("0", resolution2);
		Mobile mobile2 = new Mobile(2015001, "Apple", "iPhone 6s", dfeatures2);		
		int mobileWidth2 = mService.getMobileScreenWidth(mobile2);
		System.out.println("Apple iPhone 16s Screen Width = " + mobileWidth2);

	}

} 

输出

 Apple iPhone 6s Screen Width = 750
Apple iPhone 16s Screen Width = 0 

7.Java 8 可选

现在使用 Java 8 可选结构以干净整洁的方式开发相同的领域模型。

没有变化。请参考以上部分。

DisplayFeatures.java

 package com.mkyong.with.optional;

import java.util.Optional;

public class DisplayFeatures {

	private String size; // In inches
	private Optional&lt;ScreenResolution&gt; resolution;

	public DisplayFeatures(String size, Optional<ScreenResolution> resolution){
		this.size = size;
		this.resolution = resolution;
	}

	public String getSize() {
		return size;
	}
	public Optional<ScreenResolution> getResolution() {
		return resolution;
	}

} 

Mobile.java

 package com.mkyong.with.optional;

import java.util.Optional;

public class Mobile {

	private long id;
	private String brand;
	private String name;
	private Optional&lt;DisplayFeatures&gt; displayFeatures;
	// Like wise we can see MemoryFeatures, CameraFeatures etc.
	// For simplicity, using only one Features

	public Mobile(long id, String brand, String name, Optional&lt;DisplayFeatures&gt; displayFeatures){
		this.id = id;
		this.brand = brand;
		this.name = name;
		this.displayFeatures = displayFeatures;
	}

	public long getId() {
		return id;
	}

	public String getBrand() {
		return brand;
	}

	public String getName() {
		return name;
	}

	public Optional&lt;DisplayFeatures&gt; getDisplayFeatures() {
		return displayFeatures;
	}

} 

在这里,我们可以观察到如何清理我们的getMobileScreenWidth() API,而没有空检查和锅炉板代码。我们不担心运行时的 NullPointerExceptions。

MobileService.java

 package com.mkyong.with.optional;

import java.util.Optional;

public class MobileService {

  public Integer getMobileScreenWidth(Optional<Mobile> mobile){
	return mobile.flatMap(Mobile::getDisplayFeatures)
		 .flatMap(DisplayFeatures::getResolution)
		 .map(ScreenResolution::getWidth)
		 .orElse(0);

  }

} 

现在开发一个测试组件

MobileTesterWithOptional.java

 package com.mkyong.with.optional;

import java.util.Optional;

public class MobileTesterWithOptional {

  public static void main(String[] args) {
	ScreenResolution resolution = new ScreenResolution(750,1334);
	DisplayFeatures dfeatures = new DisplayFeatures("4.7", Optional.of(resolution));
	Mobile mobile = new Mobile(2015001, "Apple", "iPhone 6s", Optional.of(dfeatures));

	MobileService mService = new MobileService();

	int width = mService.getMobileScreenWidth(Optional.of(mobile));
	System.out.println("Apple iPhone 6s Screen Width = " + width);

	Mobile mobile2 = new Mobile(2015001, "Apple", "iPhone 6s", Optional.empty());		
	int width2 = mService.getMobileScreenWidth(Optional.of(mobile2));
	System.out.println("Apple iPhone 16s Screen Width = " + width2);
  }
} 

输出

 Apple iPhone 6s Screen Width = 750
Apple iPhone 16s Screen Width = 0 

8.Java Optional 适合哪里?

如果我们观察上面的实时零售领域用例,我们应该知道 Java 可选结构在以下地方是有用的。

8.1 方法参数

 public void setResolution(Optional<ScreenResolution> resolution) {
	this.resolution = resolution;
} 

8.2 方法返回类型

 public Optional<ScreenResolution> getResolution() {
	return resolution;
} 

8.3 构造函数参数

 public DisplayFeatures(String size, Optional<ScreenResolution> resolution){
	this.size = size;
	this.resolution = resolution;
} 

8.4 变量声明

 private Optional<ScreenResolution> resolution; 

8.5 班级水平

 public class B

public class A<T extends Optional<B>> { } 

下载源代码

Download – Java8Optional-example.zip (4 KB)

参考

  1. OptionalJavaDoc

Tags : java8 optionalfreestar.config.enabled_slots.push({ placementName: "mkyong_leaderboard_btf", slotId: "mkyong_leaderboard_btf" });

Java 8 并行流示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-parallel-streams-examples/

parallel streams high load

几个并行执行流的 Java 8 例子。

1.BaseStream.parallel()

打印 1 到 10 的简单并行示例。

ParallelExample1.java

 package com.mkyong.java8;

import java.util.stream.IntStream;

public class ParallelExample1 {

    public static void main(String[] args) {

        System.out.println("Normal...");

		IntStream range = IntStream.rangeClosed(1, 10);
        range.forEach(System.out::println);

        System.out.println("Parallel...");

        IntStream range2 = IntStream.rangeClosed(1, 10);
        range2.parallel().forEach(System.out::println);

    }

} 

输出

 Normal...
1
2
3
4
5
6
7
8
9
10

Parallel...
7
6
8
9
10
1
4
5
3
2 

2.Collection.parallelStream()

另一个简单的并行例子是打印az。对于收藏,我们可以用parallelStream()

ParallelExample2.java

 package com.mkyong.java8;

import java.util.ArrayList;
import java.util.List;

public class ParallelExample2 {

    public static void main(String[] args) {

        System.out.println("Normal...");

        List<String> alpha = getData();
        alpha.stream().forEach(System.out::println);

        System.out.println("Parallel...");

        List<String> alpha2 = getData();
        alpha2.parallelStream().forEach(System.out::println);

    }

    private static List<String> getData() {

        List<String> alpha = new ArrayList<>();

        int n = 97;  // 97 = a , 122 = z
        while (n <= 122) {
            char c = (char) n;
            alpha.add(String.valueOf(c));
            n++;
        }

        return alpha;

    }

} 

输出

 Normal...
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
Parallel...
q
s
r
o
x
h
l
p
d
i
g
t
u
n
z
v
j
k
w
f
m
c
a
e
b
y 

3.Stream 是否以并行模式运行?

3.1 我们可以用isParallel()来测试

ParallelExample3a.java

 package com.mkyong.java8;

import java.util.stream.IntStream;

public class ParallelExample3a {

    public static void main(String[] args) {

        System.out.println("Normal...");

        IntStream range = IntStream.rangeClosed(1, 10);
        System.out.println(range.isParallel());         // false
        range.forEach(System.out::println);

        System.out.println("Parallel...");

        IntStream range2 = IntStream.rangeClosed(1, 10);
        IntStream range2Parallel = range2.parallel();
        System.out.println(range2Parallel.isParallel()); // true
        range2Parallel.forEach(System.out::println);

    }

} 

3.2 或者像这样打印当前线程名:

ParallelExample3b.java

 package com.mkyong.java8;

import java.util.stream.IntStream;

public class ParallelExample3b {

    public static void main(String[] args) {

        System.out.println("Normal...");

        IntStream range = IntStream.rangeClosed(1, 10);
        range.forEach(x -> {
            System.out.println("Thread : " + Thread.currentThread().getName() + ", value: " + x);
        });

        System.out.println("Parallel...");

        IntStream range2 = IntStream.rangeClosed(1, 10);
        range2.parallel().forEach(x -> {
            System.out.println("Thread : " + Thread.currentThread().getName() + ", value: " + x);
        });

    }

} 

输出

 Normal...
Thread : main, value: 1
Thread : main, value: 2
Thread : main, value: 3
Thread : main, value: 4
Thread : main, value: 5
Thread : main, value: 6
Thread : main, value: 7
Thread : main, value: 8
Thread : main, value: 9
Thread : main, value: 10

Parallel...
Thread : main, value: 7
Thread : main, value: 6
Thread : ForkJoinPool.commonPool-worker-5, value: 3
Thread : ForkJoinPool.commonPool-worker-7, value: 8
Thread : ForkJoinPool.commonPool-worker-5, value: 5
Thread : ForkJoinPool.commonPool-worker-5, value: 4
Thread : ForkJoinPool.commonPool-worker-3, value: 9
Thread : ForkJoinPool.commonPool-worker-5, value: 1
Thread : ForkJoinPool.commonPool-worker-7, value: 2
Thread : ForkJoinPool.commonPool-worker-9, value: 10 

默认情况下,并行流使用“forkjoinpool”

4.计算

4.1 Java 8 流打印所有 100 万以内的质数:

ParallelExample4.java

 package com.mkyong.java8;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class ParallelExample4 {

    public static void main(String[] args) {

        long count = Stream.iterate(0, n -> n + 1)
                .limit(1_000_000)
                //.parallel()   with this 23s, without this 1m 10s
                .filter(ParallelExample4::isPrime)
                .peek(x -> System.out.format("%s\t", x))
                .count();

        System.out.println("\nTotal: " + count);

    }

    public static boolean isPrime(int number) {
        if (number <= 1) return false;
        return !IntStream.rangeClosed(2, number / 2).anyMatch(i -> number % i == 0);
    }

} 

结果:

  • 对于普通流,需要 1 分 10 秒。
  • 对于并行流,需要 23 秒。

PS 测试使用 i7-7700,16G 内存,WIndows 10

4.2 另一个并行流示例,用于找出雇员列表的平均年龄。

 List<Employee> employees = obj.generateEmployee(10000);

	double age = employees
			.parallelStream()
			.mapToInt(Employee::getAge)
			.average()
			.getAsDouble();

    System.out.println("Average age: " + age); 

5.个案研究

5.1 并行流提高了耗时的保存文件任务的性能。

这段 Java 代码将生成 10,000 个随机雇员,并保存到 10,000 个文件中,每个雇员保存到一个文件中。

  • 正常流的话需要 27-29 秒。
  • 对于并行流,需要 7-8 秒。

PS 测试使用 i7-7700,16G 内存,WIndows 10

ParallelExample5.java

 package com.mkyong.java8;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class ParallelExample5 {

    private static final String DIR = System.getProperty("user.dir") + "/test/";

    public static void main(String[] args) throws IOException {

        Files.createDirectories(Paths.get(DIR));

        ParallelExample5 obj = new ParallelExample5();

        List<Employee> employees = obj.generateEmployee(10000);

		// normal, sequential
        //employees.stream().forEach(ParallelExample5::save); 		// 27s-29s

		// parallel
        employees.parallelStream().forEach(ParallelExample5::save); // 7s-8s

    }

    private static void save(Employee input) {

        try (FileOutputStream fos = new FileOutputStream(new File(DIR + input.getName() + ".txt"));
             ObjectOutputStream obs = new ObjectOutputStream(fos)) {
            obs.writeObject(input);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private List<Employee> generateEmployee(int num) {

        return Stream.iterate(0, n -> n + 1)
                .limit(num)
                .map(x -> {
                    return new Employee(
                            generateRandomName(4),
                            generateRandomAge(15, 100),
                            generateRandomSalary(900.00, 200_000.00)
                    );
                })
                .collect(Collectors.toList());

    }

    private String generateRandomName(int length) {

        return new Random()
                .ints(5, 97, 122) // 97 = a , 122 = z
                .mapToObj(x -> String.valueOf((char) x))
                .collect(Collectors.joining());

    }

    private int generateRandomAge(int min, int max) {
        return new Random()
                .ints(1, min, max)
                .findFirst()
                .getAsInt();
    }

    private BigDecimal generateRandomSalary(double min, double max) {
        return new BigDecimal(new Random()
                .doubles(1, min, max)
                .findFirst()
                .getAsDouble()).setScale(2, RoundingMode.HALF_UP);
    }

} 

Employee.java

 package com.mkyong.java8;

import java.io.Serializable;
import java.math.BigDecimal;

public class Employee implements Serializable {

    private static final long serialVersionUID = 1L;

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

    //getters, setters n etc...

} 

参考

Java 8–周期和持续时间示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-period-and-duration-examples/

几个例子向你展示如何使用 Java 8 DurationPeriodChronoUnit对象找出日期之间的差异。

  1. 持续时间–以秒和纳秒为单位测量时间。
  2. period–以年、月和日为单位测量时间。

1.持续时间示例

一个java.time.Duration示例,用于找出两个LocalDateTime之间的秒数差异

DurationExample.java

 package com.mkyong.time;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.temporal.ChronoUnit;

public class DurationExample {

    public static void main(String[] args) {

		// Creating Durations
        System.out.println("--- Examples --- ");

        Duration oneHours = Duration.ofHours(1);
        System.out.println(oneHours.getSeconds() + " seconds");

        Duration oneHours2 = Duration.of(1, ChronoUnit.HOURS);
        System.out.println(oneHours2.getSeconds() + " seconds");

		// Test Duration.between
        System.out.println("\n--- Duration.between --- ");

        LocalDateTime oldDate = LocalDateTime.of(2016, Month.AUGUST, 31, 10, 20, 55);
        LocalDateTime newDate = LocalDateTime.of(2016, Month.NOVEMBER, 9, 10, 21, 56);

        System.out.println(oldDate);
        System.out.println(newDate);

        //count seconds between dates
        Duration duration = Duration.between(oldDate, newDate);

        System.out.println(duration.getSeconds() + " seconds");

    }
} 

输出

 --- Examples --- 
3600 seconds
3600 seconds

--- Duration.between --- 
2016-08-31T10:20:55
2016-11-09T10:21:56
6048061 seconds 

2.期间示例

一个java.time.Period示例,用于找出两个LocalDates之间的不同(年、月、日)

PeriodExample.java

 package com.mkyong.time;

import java.time.LocalDate;
import java.time.Month;
import java.time.Period;

public class PeriodExample {

    public static void main(String[] args) {

        System.out.println("--- Examples --- ");

        Period tenDays = Period.ofDays(10); 
        System.out.println(tenDays.getDays()); //10

        Period oneYearTwoMonthsThreeDays = Period.of(1, 2, 3);
        System.out.println(oneYearTwoMonthsThreeDays.getYears());   //1
        System.out.println(oneYearTwoMonthsThreeDays.getMonths());  //2
        System.out.println(oneYearTwoMonthsThreeDays.getDays());    //3

        System.out.println("\n--- Period.between --- ");
        LocalDate oldDate = LocalDate.of(1982, Month.AUGUST, 31);
        LocalDate newDate = LocalDate.of(2016, Month.NOVEMBER, 9);

        System.out.println(oldDate);
        System.out.println(newDate);

        // check period between dates
        Period period = Period.between(oldDate, newDate);

        System.out.print(period.getYears() + " years,");
        System.out.print(period.getMonths() + " months,");
        System.out.print(period.getDays() + " days");

    }
} 

输出

 --- Examples --- 
10
1
2
3

--- Period.between --- 
1982-08-31
2016-11-09
34 years,2 months,9 days 

3.计时单位示例

或者,您可以使用ChronoUnit.{unit}.between找出日期之间的差异,查看以下示例:

ChronoUnitExample.java

 package com.mkyong.time;

import java.time.LocalDateTime;
import java.time.Month;
import java.time.temporal.ChronoUnit;

public class ChronoUnitExample {

    public static void main(String[] args) {

        LocalDateTime oldDate = LocalDateTime.of(1982, Month.AUGUST, 31, 10, 20, 55);
        LocalDateTime newDate = LocalDateTime.of(2016, Month.NOVEMBER, 9, 10, 21, 56);

        System.out.println(oldDate);
        System.out.println(newDate);

        // count between dates
        long years = ChronoUnit.YEARS.between(oldDate, newDate);
        long months = ChronoUnit.MONTHS.between(oldDate, newDate);
        long weeks = ChronoUnit.WEEKS.between(oldDate, newDate);
        long days = ChronoUnit.DAYS.between(oldDate, newDate);
        long hours = ChronoUnit.HOURS.between(oldDate, newDate);
        long minutes = ChronoUnit.MINUTES.between(oldDate, newDate);
        long seconds = ChronoUnit.SECONDS.between(oldDate, newDate);
        long milis = ChronoUnit.MILLIS.between(oldDate, newDate);
        long nano = ChronoUnit.NANOS.between(oldDate, newDate);

        System.out.println("\n--- Total --- ");
        System.out.println(years + " years");
        System.out.println(months + " months");
        System.out.println(weeks + " weeks");
        System.out.println(days + " days");
        System.out.println(hours + " hours");
        System.out.println(minutes + " minutes");
        System.out.println(seconds + " seconds");
        System.out.println(milis + " milis");
        System.out.println(nano + " nano");

    }
} 

输出

 1982-08-31T10:20:55
2016-11-09T10:21:56

--- Total --- 
34 years
410 months
1784 weeks
12489 days
299736 hours
17984161 minutes
1079049661 seconds
1079049661000 milis
1079049661000000000 nano 

参考

  1. 甲骨文教程–周期和持续时间
  2. 持续时间 JavaDoc
  3. 句号 JavaDoc
  4. 计时单位 JavaDoc

Java 8 谓词示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-predicate-examples/

在 Java 8 中,谓词是一个函数接口,它接受一个参数并返回一个布尔值。通常,它用于对象集合的过滤器中。

 @FunctionalInterface
public interface Predicate<T> {
  boolean test(T t);
} 

延伸阅读
Java 8 双预测例题

1.过滤器()中的谓词

filter()接受谓词作为参数。

Java8Predicate.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Java8Predicate {

    public static void main(String[] args) {

        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        List<Integer> collect = list.stream().filter(x -> x > 5).collect(Collectors.toList());

        System.out.println(collect); // [6, 7, 8, 9, 10]

    }

} 

输出

 [6, 7, 8, 9, 10] 

Java8Predicate.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class Java8Predicate {

    public static void main(String[] args) {

        Predicate<Integer> noGreaterThan5 =  x -> x > 5;

        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        List<Integer> collect = list.stream()
                .filter(noGreaterThan5)
                .collect(Collectors.toList());

        System.out.println(collect); // [6, 7, 8, 9, 10]

    }

} 

输出

 [6, 7, 8, 9, 10] 

2.谓词. and()

2.1 多重过滤器。

Java8Predicate2.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Java8Predicate2 {

    public static void main(String[] args) {

        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        // multiple filters
        List<Integer> collect = list.stream()
                .filter(x -> x > 5 && x < 8).collect(Collectors.toList());

        System.out.println(collect);

    }

} 

输出

 [6, 7] 

2.1 替换为Predicate.and()

Java8Predicate2.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class Java8Predicate2 {

    public static void main(String[] args) {

        Predicate<Integer> noGreaterThan5 = x -> x > 5;
        Predicate<Integer> noLessThan8 = x -> x < 8;

        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        List<Integer> collect = list.stream()
                .filter(noGreaterThan5.and(noLessThan8))
                .collect(Collectors.toList());

        System.out.println(collect);

    }

} 

输出

 [6, 7] 

3.谓词. or()

Java8Predicate3.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class Java8Predicate3 {

    public static void main(String[] args) {

        Predicate<String> lengthIs3 = x -> x.length() == 3;
        Predicate<String> startWithA = x -> x.startsWith("A");

        List<String> list = Arrays.asList("A", "AA", "AAA", "B", "BB", "BBB");

        List<String> collect = list.stream()
                .filter(lengthIs3.or(startWithA))
                .collect(Collectors.toList());

        System.out.println(collect);

    }

} 

输出

 [A, AA, AAA, BBB] 

4.Predicate.negate()

查找不以“A”开头的所有元素。

Java8Predicate4.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class Java8Predicate4 {

    public static void main(String[] args) {

        Predicate<String> startWithA = x -> x.startsWith("A");

        List<String> list = Arrays.asList("A", "AA", "AAA", "B", "BB", "BBB");

        List<String> collect = list.stream()
                .filter(startWithA.negate())
                .collect(Collectors.toList());

        System.out.println(collect);

    }

} 

输出

 [B, BB, BBB] 

5.函数中的 Predicate.test()

函数中的谓词。

Java8Predicate5.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class Java8Predicate5 {

    public static void main(String[] args) {

        List<String> list = Arrays.asList("A", "AA", "AAA", "B", "BB", "BBB");

        System.out.println(StringProcessor.filter(
                list, x -> x.startsWith("A")));                    // [A, AA, AAA]

        System.out.println(StringProcessor.filter(
                list, x -> x.startsWith("A") && x.length() == 3)); // [AAA]

    }

}

class StringProcessor {
    static List<String> filter(List<String> list, Predicate<String> predicate) {
        return list.stream().filter(predicate::test).collect(Collectors.toList());
    }
} 

输出

 [A, AA, AAA]
[AAA] 

6.谓词链接

我们可以将谓词链接在一起。

Java8Predicate6.java

 package com.mkyong.java8;

import java.util.function.Predicate;

public class Java8Predicate6 {

    public static void main(String[] args) {

        Predicate<String> startWithA = x -> x.startsWith("a");

        // start with "a" or "m"
        boolean result = startWithA.or(x -> x.startsWith("m")).test("mkyong");
        System.out.println(result);     // true

        // !(start with "a" and length is 3)
        boolean result2 = startWithA.and(x -> x.length() == 3).negate().test("abc");
        System.out.println(result2);    // false

    }

} 

输出

 true
false 

7.宾语中的谓语

Hosting.java

 package com.mkyong.java8;

public class Hosting {

    private int Id;
    private String name;
    private String url;

    public Hosting(int id, String name, String url) {
        Id = id;
        this.name = name;
        this.url = url;
    }

    //... getters and setters, toString()
} 

HostingRespository.java

 package com.mkyong.java8;

import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class HostingRespository {

    public static List<Hosting> filterHosting(List<Hosting> hosting,
                                              Predicate<Hosting> predicate) {
        return hosting.stream()
                .filter(predicate)
                .collect(Collectors.toList());
    }

} 

Java8Predicate7.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class Java8Predicate7 {

    public static void main(String[] args) {

        Hosting h1 = new Hosting(1, "amazon", "aws.amazon.com");
        Hosting h2 = new Hosting(2, "linode", "linode.com");
        Hosting h3 = new Hosting(3, "liquidweb", "liquidweb.com");
        Hosting h4 = new Hosting(4, "google", "google.com");

        List<Hosting> list = Arrays.asList(new Hosting[]{h1, h2, h3, h4});

        List<Hosting> result = HostingRespository.filterHosting(list, x -> x.getName().startsWith("g"));
        System.out.println("result : " + result);  // google

        List<Hosting> result2 = HostingRespository.filterHosting(list, isDeveloperFriendly());
        System.out.println("result2 : " + result2); // linode

    }

    public static Predicate<Hosting> isDeveloperFriendly() {
        return n -> n.getName().equals("linode");
    }
} 

输出

 result : [Hosting{Id=4, name='google', url='google.com'}]
result2 : [Hosting{Id=2, name='linode', url='linode.com'}] 

完成了。

参考

Java 8——我们应该在使用后关闭流吗?

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-8-should-we-close-the-stream-after-use/

只有来源为 IO 通道(如Files.lines(Path, Charset))的流才需要关闭。

阅读这个流 JavaDocs

流有一个 BaseStream.close()方法并实现 AutoCloseable,但是几乎所有的流实例在使用后都不需要关闭。通常,只有来源为 IO 通道的流(如 Files.lines(Path,Charset)返回的流)才需要关闭。大多数流由集合、数组或生成函数支持,不需要特殊的资源管理。(如果流确实需要关闭,可以在 try-with-resources 语句中将其声明为资源。)

1.对于像这样的普通流,流实例在使用后不需要关闭。

Java8StreamExample.java

 package com.mkyong;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Java8StreamExample {

    public static void main(String[] args) {

        Stream<String> stream = Stream.of("A", "B", "C");

        List<String> filter = stream.filter(x -> !x.equalsIgnoreCase("B"))
			.collect(Collectors.toList());

        // no need close the stream.
        //stream.close();

        System.out.println(filter); // [A, C]

    }

} 

2.对于来源为 IO 通道的流,用try-with-resources将其关闭

Java8StreamIO.java

 package com.mkyong;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Java8StreamIO {

    public static void main(String[] args) {

        String path = "c:\\projects\\app.log";

		// auto close
        try (Stream<String> lines = Files.lines(Paths.get(path))) {

            String content = lines.collect(Collectors.joining(System.lineSeparator()));

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

} 

参考

Tags : java 8 stream

Java 8 流–将List<List<String>>转换为List<String>

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-8-stream-convert-listliststring-to-liststring/

如题,我们可以用flatMap来转换。

Java9Example1.java

 package com.mkyong.test;

import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;

public class Java9Example1 {

    public static void main(String[] args) {

        List<String> numbers = Arrays.asList("1", "2", "A", "B", "C1D2E3");

        List<List<String>> collect = numbers.stream()
                .map(x -> new Scanner(x).findAll("\\D+")
                        .map(m -> m.group())
                        .collect(Collectors.toList())
                )
                .collect(Collectors.toList());

        collect.forEach(x -> System.out.println(x));

    }

} 

输出

 []
[]
[A]
[B]
[C, D, E] 

解决办法

Java9Example2.java

 package com.mkyong.test;

import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;

public class Java9Example2 {

    public static void main(String[] args) {

        List<String> numbers = Arrays.asList("1", "2", "A", "B", "C1D2E3");

        List<String> collect = numbers.stream()
                .map(x -> new Scanner(x).findAll("\\D+")
                        .map(m -> m.group())
                        .collect(Collectors.toList())
                )									 	// List<List<String>>
                .flatMap(List::stream)					// List<String>
                .collect(Collectors.toList());

        collect.forEach(x -> System.out.println(x));

    }

} 

输出

 A
B
C
D
E 

参考

Java 8 流 findFirst()和 findAny()

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-stream-findfirst-and-findany/

在 Java 8 流中,findFirst()返回流中的第一个元素,而findAny()返回流中的任何元素。

1.findFirst()

1.1 从整数流中找到第一个元素。

Java8FindFirstExample1.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class Java8FindFirstExample1 {

    public static void main(String[] args) {

        List<Integer> list = Arrays.asList(1, 2, 3, 2, 1);

        Optional<Integer> first = list.stream().findFirst();
        if (first.isPresent()) {
            Integer result = first.get();
            System.out.println(result);       // 1
        } else {
            System.out.println("no value?");
        }

        Optional<Integer> first2 = list
                .stream()
                .filter(x -> x > 1).findFirst();

        if (first2.isPresent()) {
            System.out.println(first2.get()); // 2
        } else {
            System.out.println("no value?");
        }
    }

} 

输出

 1
2 

1.2 从字符串流中找到不等于“node”的第一个元素。

Java8FindFirstExample2.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class Java8FindFirstExample2 {

    public static void main(String[] args) {

        List<String> list = Arrays.asList("node", "java", "python", "ruby");

        Optional<String> result = list.stream()
                .filter(x -> !x.equalsIgnoreCase("node"))
                .findFirst();

        if (result.isPresent()) {
            System.out.println(result.get()); // java
        } else {
            System.out.println("no value?");
        }

    }

} 

输出

 java 

2. findAny()

2.1 从整数流中找出任意元素。如果我们运行下面的程序,大多数情况下,结果是 2,看起来findAny()总是返回第一个元素?但是,不能保证能做到这一点,findAny()可以从流中返回任何元素。

Java8FindAnyExample1.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class Java8FindAnyExample1 {

    public static void main(String[] args) {

        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        Optional<Integer> any = list.stream().filter(x -> x > 1).findAny();
        if (any.isPresent()) {
            Integer result = any.get();
            System.out.println(result);
        }

    }

} 

输出

 2 // no guaranteed 

参考

Java 8 Stream.iterate 示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-stream-iterate-examples/

在 Java 8 中,我们可以使用Stream.iterate按需创建流值,也就是所谓的无限流。

1.Stream.iterate

1.1 0–9 的流

 //Stream.iterate(initial value, next value)
	Stream.iterate(0, n -> n + 1)
                .limit(10)
                .forEach(x -> System.out.println(x)); 

输出

 0
1
2
3
4
5
6
7
8
9 

1.2 仅奇数流。

 Stream.iterate(0, n -> n + 1)
			.filter(x -> x % 2 != 0) //odd
			.limit(10)
			.forEach(x -> System.out.println(x)); 

输出

 1
3
5
7
9
11
13
15
17
19 

1.3 一个经典的斐波那契例子。

 Stream.iterate(new int[]{0, 1}, n -> new int[]{n[1], n[0] + n[1]})
		.limit(20)
		.map(n -> n[0])
		.forEach(x -> System.out.println(x)); 

输出

 0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181 

1.4 对所有斐波纳契值求和。

 int sum = Stream.iterate(new int[]{0, 1}, n -> new int[]{n[1], n[0] + n[1]})
                .limit(10)
                .map(n -> n[0]) // Stream<Integer>
                .mapToInt(n -> n)
                .sum();

        System.out.println("Fibonacci 10 sum : " + sum); 

输出

 Fibonacci 10 sum : 88 

2.Java 9

Java 9 中增强了stream.iterate。它支持一个谓词(条件)作为第二个参数,如果谓词为假,stream.iterate将停止。

2.1 如果n >= 20,停止流迭代

 Stream.iterate(1, n -> n < 20 , n -> n * 2)
           .forEach(x -> System.out.println(x)); 

输出

 1
2
4
8
16 

参考

  1. Oracle 文档–Java 流迭代

Java 8 流——逐行读取文件

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-stream-read-a-file-line-by-line/

在 Java 8 中,你可以使用Files.lines作为Stream来读取文件。

c://lines.txt – A simple text file for testing

 line1
line2
line3
line4
line5 

1.Java 8 读文件+流

TestReadFile.java

 package com.mkyong.java8;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;

public class TestReadFile {

	public static void main(String args[]) {

		String fileName = "c://lines.txt";

		//read file into stream, try-with-resources
		try (Stream<String> stream = Files.lines(Paths.get(fileName))) {

			stream.forEach(System.out::println);

		} catch (IOException e) {
			e.printStackTrace();
		}

	}

} 

输出

 line1
line2
line3
line4
line5 

2.Java 8 读文件+流+额外

这个例子向你展示了如何使用Stream来过滤内容,将整个内容转换成大写字母,并作为一个List返回。

TestReadFile2.java

 package com.mkyong.java8;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class TestReadFile2 {

	public static void main(String args[]) {

		String fileName = "c://lines.txt";
		List<String> list = new ArrayList<>();

		try (Stream<String> stream = Files.lines(Paths.get(fileName))) {

			//1\. filter line 3
			//2\. convert all content to upper case
			//3\. convert it into a List
			list = stream
					.filter(line -> !line.startsWith("line3"))
					.map(String::toUpperCase)
					.collect(Collectors.toList());

		} catch (IOException e) {
			e.printStackTrace();
		}

		list.forEach(System.out::println);

	}

} 

输出

 LINE1
LINE2
LINE4
LINE5 

3.BufferedReader + Stream

从 1.8 开始增加了一个新方法lines(),它让BufferedReaderStream的形式返回内容。

TestReadFile3.java

 package com.mkyong.java8;

import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class TestReadFile3{

	public static void main(String args[]) {

		String fileName = "c://lines.txt";
		List<String> list = new ArrayList<>();

		try (BufferedReader br = Files.newBufferedReader(Paths.get(fileName))) {

			//br returns as stream and convert it into a List
			list = br.lines().collect(Collectors.toList());

		} catch (IOException e) {
			e.printStackTrace();
		}

		list.forEach(System.out::println);

	}

} 

输出

 line1
line2
line3
line4
line5 

4.经典缓冲阅读器和扫描仪

受够了 Java 8 和Stream,让我们重温一下经典的BufferedReader (JDK1.1)和Scanner (JDK1.5)的例子来逐行读取一个文件,它仍然在工作,只是开发者正在向Stream前进。

4.1 BufferedReader +资源尝试示例。

TestReadFile4.java

 package com.mkyong.core;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class TestReadFile4{

	public static void main(String args[]) {

		String fileName = "c://lines.txt";

		try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {

			String line;
			while ((line = br.readLine()) != null) {
				System.out.println(line);
			}

		} catch (IOException e) {
			e.printStackTrace();
		}

	}

} 

4.2 Scanner +用资源试试看的例子。

TestReadFile5.java

 package com.mkyong.core;

import java.io.File;
import java.io.IOException;
import java.util.Scanner;

public class TestReadFile5 {

	public static void main(String args[]) {

		String fileName = "c://lines.txt";

		try (Scanner scanner = new Scanner(new File(fileName))) {

			while (scanner.hasNext()){
				System.out.println(scanner.nextLine());
			}

		} catch (IOException e) {
			e.printStackTrace();
		}

	}

} 

参考

  1. Java 8 File.lines()
  2. Java 8 流
  3. Java 缓冲器

Tags : java8 read file stream

Java 8 Stream.reduce()示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-stream-reduce-examples/

在 Java 8 中,Stream.reduce()组合流中的元素并产生一个值。

使用 for 循环的简单求和运算。

 int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  int sum = 0;
  for (int i : numbers) {
      sum += i;
  }

  System.out.println("sum : " + sum); // 55 

Stream.reduce()中的等价物

 int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

  // 1st argument, init value = 0
  int sum = Arrays.stream(numbers).reduce(0, (a, b) -> a + b);

  System.out.println("sum : " + sum); // 55 

或者用Integer::sum引用方法

 int sum = Arrays.stream(numbers).reduce(0, Integer::sum); // 55 

Integer.java

 /**
     * Adds two integers together as per the + operator.
     *
     * @param a the first operand
     * @param b the second operand
     * @return the sum of {@code a} and {@code b}
     * @see java.util.function.BinaryOperator
     * @since 1.8
     */
    public static int sum(int a, int b) {
        return a + b;
    } 

1.方法签名

1.1 查看Stream.reduce()方法签名:

Stream.java

 T reduce(T identity, BinaryOperator<T> accumulator); 

IntStream.java

 int reduce(int identity, IntBinaryOperator op); 

LongStream.java

 long reduce(int identity, LongBinaryOperator op); 
  • identity =默认值或初始值。
  • BinaryOperator =函数接口,取两个值并产生一个新值。

1.2 如果缺少identity参数,则没有默认值或初始值,它返回一个可选的。

Stream.java

 Optional<T> reduce(BinaryOperator<T> accumulator); 

2.更多示例

2.1 数学运算。

 int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

int sum = Arrays.stream(numbers).reduce(0, (a, b) -> a + b);    // 55
int sum2 = Arrays.stream(numbers).reduce(0, Integer::sum);      // 55

int sum3 = Arrays.stream(numbers).reduce(0, (a, b) -> a - b);   // -55
int sum4 = Arrays.stream(numbers).reduce(0, (a, b) -> a * b);   // 0, initial is 0, 0 * whatever = 0
int sum5 = Arrays.stream(numbers).reduce(0, (a, b) -> a / b);   // 0 

2.2 最大和最小。

 int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

int max = Arrays.stream(numbers).reduce(0, (a, b) -> a > b ? a : b);  // 10
int max1 = Arrays.stream(numbers).reduce(0, Integer::max);            // 10

int min = Arrays.stream(numbers).reduce(0, (a, b) -> a < b ? a : b);  // 0
int min1 = Arrays.stream(numbers).reduce(0, Integer::min);            // 0 

2.3 连接字符串。

 String[] strings = {"a", "b", "c", "d", "e"};

  // |a|b|c|d|e , the initial | join is not what we want
  String reduce = Arrays.stream(strings).reduce("", (a, b) -> a + "|" + b);

  // a|b|c|d|e, filter the initial "" empty string
  String reduce2 = Arrays.stream(strings).reduce("", (a, b) -> {
      if (!"".equals(a)) {
          return a + "|" + b;
      } else {
          return b;
      }
  });

  // a|b|c|d|e , better uses the Java 8 String.join :)
  String join = String.join("|", strings); 

3.映射和缩小

一个简单的映射和简化示例,用于从发票列表中对BigDecimal求和。

JavaReduce.java

 package com.mkyong;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.List;

public class JavaReduce {

    public static void main(String[] args) {

        List<Invoice> invoices = Arrays.asList(
                new Invoice("A01", BigDecimal.valueOf(9.99), BigDecimal.valueOf(1)),
                new Invoice("A02", BigDecimal.valueOf(19.99), BigDecimal.valueOf(1.5)),
                new Invoice("A03", BigDecimal.valueOf(4.99), BigDecimal.valueOf(2))
        );

        BigDecimal sum = invoices.stream()
                .map(x -> x.getQty().multiply(x.getPrice()))    // map
                .reduce(BigDecimal.ZERO, BigDecimal::add);      // reduce

        System.out.println(sum);    // 49.955
        System.out.println(sum.setScale(2, RoundingMode.HALF_UP));  // 49.96

    }

}

class Invoice {

    String invoiceNo;
    BigDecimal price;
    BigDecimal qty;

    // getters, stters n constructor
} 

输出

 49.955
49.96 

参考

Java 8 Stream–peek()不支持 count()?

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-stream-the-peek-is-not-working-with-count/

许多例子都使用.count()作为.peek()的终端操作,例如:

Java 8

 List<String> l = Arrays.asList("A", "B", "C", "D");

	long count = l.stream().peek(System.out::println).count();

	System.out.println(count); // 4 

输出——工作正常。

 A
B
C
D
4 

然而,对于 Java 9 和更高版本,peek()可能什么也不打印:

Java 9 and above

 List<String> l = Arrays.asList("A", "B", "C", "D");

	long count = l.stream().peek(System.out::println).count();

	System.out.println(count); // 4 

输出

 4 

为什么 peek()现在什么都不打印?

参考 Java 9 。count() Java 文档

 An implementation may choose to not execute the stream pipeline (either sequentially or in parallel) 
if it is capable of computing the count directly from the stream source. 
In such cases no source elements will be traversed and no intermediate operations will be evaluated. 

从 Java 9 开始,如果 JDK 编译器能够直接从流中计算出count(Java 9 中的优化),它就不会遍历流,所以根本不需要运行peek()

 List<String> l = Arrays.asList("A", "B", "C", "D");

	// JDK compiler know the size of the stream via the variable l 
	long count = l.stream().peek(System.out::println).count(); 

要强制peek()运行,只需用filter()改变一些元素或切换到另一个终端操作,如collect()

filter()

 List<String> l = Arrays.asList("A", "B", "C", "D");

	long count = l.stream()
			.filter(x->!x.isEmpty())
			.peek(System.out::println)
			.count();

	System.out.println(count); // 4 

输出

 A
B
C
D
4 

collect()

 List<String> l = Arrays.asList("A", "B", "C", "D");

	List<String> result = l.stream()
			.peek(System.out::println)
			.collect(Collectors.toList());

	System.out.println(result.size()); // 4 

输出

 A
B
C
D
4 

小心混淆.peek().count()peek()在 Java 9 和更高版本中可能无法正常工作。

P.S .用 Java 12 测试

参考

Java 8 流过滤器示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/tutorials/java-8-tutorials/java8/java-8-streams-filter-examples/

在本教程中,我们将向您展示几个 Java 8 示例来演示流filter()collect()findAny()orElse()的使用

1.流过滤器()和收集()

Java 8 之前,这样过滤一个List:

BeforeJava8.java

 package com.mkyong.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class BeforeJava8 {

    public static void main(String[] args) {

        List<String> lines = Arrays.asList("spring", "node", "mkyong");
        List<String> result = getFilterOutput(lines, "mkyong");
        for (String temp : result) {
            System.out.println(temp);    //output : spring, node
        }

    }

    private static List<String> getFilterOutput(List<String> lines, String filter) {
        List<String> result = new ArrayList<>();
        for (String line : lines) {
            if (!"mkyong".equals(line)) { // we dont like mkyong
                result.add(line);
            }
        }
        return result;
    }

} 

输出

 spring
node 

1.2 Java 8 中的等价例子,stream.filter()过滤一个Listcollect()将一个流转换成一个List

NowJava8.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class NowJava8 {

    public static void main(String[] args) {

        List<String> lines = Arrays.asList("spring", "node", "mkyong");

        List<String> result = lines.stream()                // convert list to stream
                .filter(line -> !"mkyong".equals(line))     // we dont like mkyong
                .collect(Collectors.toList());              // collect the output and convert streams to a List

        result.forEach(System.out::println);                //output : spring, node

    }

} 

输出

 spring
node 

2.Streams filter()、findAny()和 orElse()

Person.java

 package com.mkyong.java8;

public class Person {

    private String name;
    private int age;

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

    //gettersm setters, toString
} 

2.1 在 Java 8 之前,你通过名字得到一个Person,像这样:

BeforeJava8.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;

public class BeforeJava8 {

    public static void main(String[] args) {

        List<Person> persons = Arrays.asList(
                new Person("mkyong", 30),
                new Person("jack", 20),
                new Person("lawrence", 40)
        );

        Person result = getStudentByName(persons, "jack");
        System.out.println(result);

    }

    private static Person getStudentByName(List<Person> persons, String name) {

        Person result = null;
        for (Person temp : persons) {
            if (name.equals(temp.getName())) {
                result = temp;
            }
        }
        return result;
    }
} 

输出

 Person{name='jack', age=20} 

2.2 Java 8 中的等价例子,使用stream.filter()过滤一个List,使用.findAny().orElse (null)返回一个有条件的对象。

NowJava8.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;

public class NowJava8 {

    public static void main(String[] args) {

        List<Person> persons = Arrays.asList(
                new Person("mkyong", 30),
                new Person("jack", 20),
                new Person("lawrence", 40)
        );

        Person result1 = persons.stream()                        // Convert to steam
                .filter(x -> "jack".equals(x.getName()))        // we want "jack" only
                .findAny()                                      // If 'findAny' then return found
                .orElse(null);                                  // If not found, return null

        System.out.println(result1);

        Person result2 = persons.stream()
                .filter(x -> "ahmook".equals(x.getName()))
                .findAny()
                .orElse(null);

        System.out.println(result2);

    }

} 

输出

 Person{name='jack', age=20}
null 

2.3 适用于多种情况。

NowJava8.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;

public class NowJava8 {

    public static void main(String[] args) {

        List<Person> persons = Arrays.asList(
                new Person("mkyong", 30),
                new Person("jack", 20),
                new Person("lawrence", 40)
        );

        Person result1 = persons.stream()
                .filter((p) -> "jack".equals(p.getName()) && 20 == p.getAge())
                .findAny()
                .orElse(null);

        System.out.println("result 1 :" + result1);

        //or like this
        Person result2 = persons.stream()
                .filter(p -> {
                    if ("jack".equals(p.getName()) && 20 == p.getAge()) {
                        return true;
                    }
                    return false;
                }).findAny()
                .orElse(null);

        System.out.println("result 2 :" + result2);

    }

} 

输出

 result 1 :Person{name='jack', age=20}
result 2 :Person{name='jack', age=20} 

3.流过滤器()和映射()

NowJava8.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class NowJava8 {

    public static void main(String[] args) {

        List<Person> persons = Arrays.asList(
                new Person("mkyong", 30),
                new Person("jack", 20),
                new Person("lawrence", 40)
        );

        String name = persons.stream()
                .filter(x -> "jack".equals(x.getName()))
                .map(Person::getName)                        //convert stream to String
                .findAny()
                .orElse("");

        System.out.println("name : " + name);

        List<String> collect = persons.stream()
                .map(Person::getName)
                .collect(Collectors.toList());

        collect.forEach(System.out::println);

    }

} 

输出

 name : jack

mkyong
jack
lawrence 

Note
Highly recommend this Streams tutorial – Processing Data with Java SE 8 Streams

参考

  1. Java 8 循环推理在我这里
  2. Java 8 解释:使用过滤器、映射、流和 Foreach 将 Lambdas 应用于 Java 集合!
  3. Java 8 forEach 示例
  4. Java 8 流:多重过滤器与复杂条件
  5. 用 Java SE 8 流处理数据

Java 8 Streams map()示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-streams-map-examples/

在 Java 8 中,stream().map()让你把一个对象转换成其他的东西。查看以下示例:

1.大写的字符串列表

1.1 将字符串列表转换成大写字母的简单 Java 示例。

TestJava8.java

 package com.mkyong.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class TestJava8 {

    public static void main(String[] args) {

        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]

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

        // 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]

    }

} 

2.对象列表->字符串列表

2.1 从staff对象列表中获取所有的name值。

Staff.java

 package com.mkyong.java8;

import java.math.BigDecimal;

public class Staff {

    private String name;
    private int age;
    private BigDecimal salary;
	//...
} 

TestJava8.java

 package com.mkyong.java8;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class TestJava8 {

    public static void main(String[] args) {

        List<Staff> staff = Arrays.asList(
                new Staff("mkyong", 30, new BigDecimal(10000)),
                new Staff("jack", 27, new BigDecimal(20000)),
                new Staff("lawrence", 33, new BigDecimal(30000))
        );

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

        //Java 8
        List<String> collect = staff.stream().map(x -> x.getName()).collect(Collectors.toList());
        System.out.println(collect); //[mkyong, jack, lawrence]

    }

} 

3.对象列表->其他对象列表

3.1 这个例子向你展示了如何将一列staff对象转换成一列StaffPublic对象。

Staff.java

 package com.mkyong.java8;

import java.math.BigDecimal;

public class Staff {

    private String name;
    private int age;
    private BigDecimal salary;
	//...
} 

StaffPublic.java

 package com.mkyong.java8;

public class StaffPublic {

    private String name;
    private int age;
    private String extra;
    //...
} 

Java 8 之前的 3.2。

BeforeJava8.java

 package com.mkyong.java8;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class BeforeJava8 {

    public static void main(String[] args) {

        List<Staff> staff = Arrays.asList(
                new Staff("mkyong", 30, new BigDecimal(10000)),
                new Staff("jack", 27, new BigDecimal(20000)),
                new Staff("lawrence", 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 ("mkyong".equals(temp.getName())) {
                obj.setExtra("this field is for mkyong only!");
            }

            result.add(obj);
        }

        return result;

    }

} 

输出

 [
	StaffPublic{name='mkyong', age=30, extra='this field is for mkyong only!'}, 
	StaffPublic{name='jack', age=27, extra='null'}, 
	StaffPublic{name='lawrence', age=33, extra='null'}
] 

3.3 Java 8 示例。

NowJava8.java

 package com.mkyong.java8;

package com.hostingcompass.web.java8;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class NowJava8 {

    public static void main(String[] args) {

        List<Staff> staff = Arrays.asList(
                new Staff("mkyong", 30, new BigDecimal(10000)),
                new Staff("jack", 27, new BigDecimal(20000)),
                new Staff("lawrence", 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 ("mkyong".equals(temp.getName())) {
                obj.setExtra("this field is for mkyong only!");
            }
            return obj;
        }).collect(Collectors.toList());

        System.out.println(result);

    }

} 

输出

 [
	StaffPublic{name='mkyong', age=30, extra='this field is for mkyong only!'}, 
	StaffPublic{name='jack', age=27, extra='null'}, 
	StaffPublic{name='lawrence', age=33, extra='null'}
] 

参考

  1. 用 Java SE 8 流处理数据,第 1 部分
  2. Java 8–过滤地图示例
  3. Java 8 平面图示例
  4. 收藏家 JavaDoc

Java 8–string joiner 示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-stringjoiner-example/

在这篇文章中,我们将向你展示一些连接字符串的例子。

1.弦乐演奏者

1.1 通过分隔符连接字符串

 StringJoiner sj = new StringJoiner(",");
        sj.add("aaa");
        sj.add("bbb");
        sj.add("ccc");
        String result = sj.toString(); //aaa,bbb,ccc 

1.2 通过分隔符连接字符串,以提供的前缀开始,以提供的后缀结束。

 StringJoiner sj = new StringJoiner("/", "prefix-", "-suffix");
        sj.add("2016");
        sj.add("02");
        sj.add("26");
        String result = sj.toString(); //prefix-2016/02/26-suffix 

2.字符串连接

StringJoiner 由 static String.join()内部使用。

2.1 用分隔符连接字符串。

 //2015-10-31
	String result = String.join("-", "2015", "10", "31" ); 

2.2 用分隔符连接一个列表

 List<String> list = Arrays.asList("java", "python", "nodejs", "ruby");
 	//java, python, nodejs, ruby
	String result = String.join(", ", list); 

3.收集器.加入

两个StreamCollectors.joining的例子。

3.1 加入List<String>示例。

 List<String> list = Arrays.asList("java", "python", "nodejs", "ruby");

	//java | python | nodejs | ruby
	String result = list.stream().map(x -> x).collect(Collectors.joining(" | ")); 

3.2 连接列表<Object>示例。

 void test(){

        List<Game> list = Arrays.asList(
                new Game("Dragon Blaze", 5),
                new Game("Angry Bird", 5),
                new Game("Candy Crush", 5)
        );

        //{Dragon Blaze, Angry Bird, Candy Crush}
        String result = list.stream().map(x -> x.getName())
			.collect(Collectors.joining(", ", "{", "}"));

    }

    class Game{
        String name;
        int ranking;

        public Game(String name, int ranking) {
            this.name = name;
            this.ranking = ranking;
        }

        public String getName() {
            return name;
        }

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

        public int getRanking() {
            return ranking;
        }

        public void setRanking(int ranking) {
            this.ranking = ranking;
        }
    } 

参考

  1. Stream–collectors . joining JavaDoc
  2. StringJoiner JavaDoc

Tags : java8

Java 8 供应商示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-supplier-examples/

在 Java 8 中,供应商是一个函数接口;它不接受任何参数并返回一个结果。

Supplier.java

 @FunctionalInterface
public interface Supplier<T> {
    T get();
} 

1.供应商

1.1 本例使用Supplier返回当前日期时间。

Java8Supplier1.java

 package com.mkyong;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.function.Supplier;

public class Java8Supplier1 {

    private static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public static void main(String[] args) {

        Supplier<LocalDateTime> s = () -> LocalDateTime.now();
        LocalDateTime time = s.get();

        System.out.println(time);

        Supplier<String> s1 = () -> dtf.format(LocalDateTime.now());
        String time2 = s1.get();

        System.out.println(time2);

    }

} 

输出

 2020-03-02T16:10:49.281223
2020-03-02 16:10:49 

2.返回供应商

Java8Supplier2.java

 package com.mkyong;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

public class Java8Supplier2<T> {

    public static void main(String[] args) {

        Java8Supplier2<String> obj = new Java8Supplier2();

        List<String> list = obj.supplier().get();

    }

    public Supplier<List<T>> supplier() {

        // lambda
        // return () -> new ArrayList<>();

        // constructor reference
        return ArrayList::new;

    }

} 

3.工厂

3.1 返回一个Developer对象的简单工厂方法。

Java8Supplier3.java

 package com.mkyong;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.function.Supplier;

public class Java8Supplier3 {

    public static void main(String[] args) {

        Developer obj = factory(Developer::new);
        System.out.println(obj);

        Developer obj2 = factory(() -> new Developer("mkyong"));
        System.out.println(obj2);

    }

    public static Developer factory(Supplier<? extends Developer> s) {

        Developer developer = s.get();
        if (developer.getName() == null || "".equals(developer.getName())) {
            developer.setName("default");
        }
        developer.setSalary(BigDecimal.ONE);
        developer.setStart(LocalDate.of(2017, 8, 8));

        return developer;

    }

} 

Developer.java

 package com.mkyong;

import java.math.BigDecimal;
import java.time.LocalDate;

public class Developer {

    String name;
    BigDecimal salary;
    LocalDate start;

    // for factory(Developer::new);
    public Developer() {
    }

    // for factory(() -> new Developer("mkyong"));
    public Developer(String name) {
        this.name = name;
    }

    // get, set, constructor, toString
    //...

} 

输出

 Developer{name='default', salary=1, start=2017-08-08}
Developer{name='mkyong', salary=1, start=2017-08-08} 

参考

Java 8 教程

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/tutorials/java-8-tutorials/

java 8 logo

一系列 Java 8 的提示和例子,希望你喜欢。

常见问题

一些常见问题。

1.功能接口

Java 8 引入了@FunctionalInterface,一个只有一个抽象方法的接口。编译器会将任何满足函数接口的定义的接口视为函数接口;这意味着@FunctionalInterface注释是可选的。

让我们看看六个基本的功能界面。

连接 签名 例子
UnaryOperator<T> T apply(T t) String::toLowerCaseMath::tan
BinaryOperator<T> T apply(T t1, T t2) BigInteger::addMath::pow
Function<T, R> R apply(T t) Arrays::asListInteger::toBinaryString
Predicate<T, U> boolean test(T t, U u) String::isEmptyCharacter::isDigit
Supplier<T> T get() LocalDate::nowInstant::now
Consumer<T> void accept(T t) System.out::printlnError::printStackTrace

2.Lambda 表达式和方法引用

Java 8 引入了 lambda 表达式来实现函数接口的抽象方法。

延伸阅读> > > Java 8 Lambda:比较器示例

回顾一下 JDK 的Iterable类,它有一个default方法forEach()来接受一个函数接口Consumer

Iterable.java

 public interface Iterable<T> {

    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

   //...
} 

首先,我们可以提供一个匿名类作为forEach实现。

 List<String> list = Arrays.asList("node", "java", "python", "ruby");
list.forEach(new Consumer<String>() {       // anonymous class
    @Override
    public void accept(String str) {
        System.out.println(str);
    }
}); 

或者,我们可以使用 lambda 表达式来缩短代码,如下所示:

 List<String> list = Arrays.asList("node", "java", "python", "ruby");
list.forEach(str -> System.out.println(str)); // lambda expressions 

为了获得更好的可读性,我们可以用方法引用替换 lambda 表达式。

 List<String> list = Arrays.asList("node", "java", "python", "ruby");
list.forEach(System.out::println);           // method references 

延伸阅读> > > Java 8 方法引用,双冒号(::)运算符

注意
lambda 表达式或方法引用什么都不做,只是对现有方法的另一种方式调用。通过方法引用,它获得了更好的可读性。

3.流

4.新日期时间 API

过去,我们使用DateCalendarAPI 来表示和操作日期。

  • java.util.Date–日期和时间,以默认时区打印。
  • java.util.Calendar–日期和时间,更多操作日期的方法。
  • java.text.SimpleDateFormat–格式化(日期- >文本),解析(文本- >日期)日期和日历。

Java 8 在java.time包中创建了一系列新的日期和时间 API。( JSR310 并受 Joda-time 启发)。

  • java.time.LocalDate–无时间、无时区的日期。
  • java.time.LocalTime–无日期、无时区的时间。
  • java.time.LocalDateTime–日期和时间,无时区。
  • java.time.ZonedDateTime–日期和时间,带时区。
  • java.time.DateTimeFormatter–Java . time 的格式化(日期- >文本)、解析(文本- >日期)
  • java.time.Instant–机器的日期和时间,自 Unix 纪元时间(世界协调时 1970 年 1 月 1 日午夜)以来经过的秒数
  • java.time.Duration–以秒和纳秒为单位测量时间。
  • java.time.Period–以年、月、日计量时间。
  • java.time.TemporalAdjuster–调整日期。
  • java.time.OffsetDateTime

示例…

5.Java 8 技巧

装置

参考

Java 8–无法从 TemporalAccessor 获取本地日期时间

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-unable-to-obtain-localdatetime-from-temporalaccessor/

一个将字符串转换为LocalDateTime的例子,但是它提示以下错误:

Java8Example.java

 package com.mkyong.demo;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Java8Example {

    public static void main(String[] args) {

        String str = "31-Aug-2020";

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd-MMM-yyyy", Locale.US);

        LocalDateTime localDateTime = LocalDateTime.parse(str, dtf);

        System.out.println(localDateTime);

    }
} 

输出

 Exception in thread "main" java.time.format.DateTimeParseException: Text '31-Aug-2020' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {},ISO resolved to 2020-08-31 of type java.time.format.Parsed
	at java.base/java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:2017)
	at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1952)
	at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:492)
	at com.mkyong.demo.Java8Example.main(Java8Example.java:15)
Caused by: java.time.DateTimeException: Unable to obtain LocalDateTime from TemporalAccessor: {},ISO resolved to 2020-08-31 of type java.time.format.Parsed
	at java.base/java.time.LocalDateTime.from(LocalDateTime.java:461)
	at java.base/java.time.format.Parsed.query(Parsed.java:235)
	at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
	... 2 more
Caused by: java.time.DateTimeException: Unable to obtain LocalTime from TemporalAccessor: {},ISO resolved to 2020-08-31 of type java.time.format.Parsed
	at java.base/java.time.LocalTime.from(LocalTime.java:431)
	at java.base/java.time.LocalDateTime.from(LocalDateTime.java:457)
	... 4 more 

解决办法

日期31-Aug-2020不包含时间,为了解决这个问题,使用LocalDate.parse(str, dtf).atStartOfDay()

 String str = "31-Aug-2020";

  DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd-MMM-yyyy", Locale.US);

  LocalDateTime localDateTime = LocalDate.parse(str, dtf).atStartOfDay(); 

参考

Java 8 一元运算符示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-unaryoperator-examples/

在 Java 8 中,一元运算符是一个函数接口,它扩展了Function

UnaryOperator接受一个参数,并返回相同类型参数的结果。

UnaryOperator.java

 @FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
} 

Function接受任意类型的一个参数并返回任意类型的结果。

Function.java

 @FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
} 

进一步阅读 Java 8 函数示例

1.一元运算符

1.1 在本例中,接受并返回相同类型的Function<Integer, Integer>可以替换为UnaryOperator<Integer>

Java8UnaryOperator1.java

 package com.mkyong;

import java.util.function.Function;
import java.util.function.UnaryOperator;

public class Java8UnaryOperator1 {

    public static void main(String[] args) {

        Function<Integer, Integer> func = x -> x * 2;

        Integer result = func.apply(2);

        System.out.println(result);         // 4

        UnaryOperator<Integer> func2 = x -> x * 2;

        Integer result2 = func2.apply(2);

        System.out.println(result2);        // 4

    }

} 

输出

 4
4 

2.UnaryOperator<T>作为参数

Java8UnaryOperator2.java

 package com.mkyong;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.UnaryOperator;

public class Java8UnaryOperator2 {

    public static void main(String[] args) {

        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        List<Integer> result = math(list, x -> x * 2);

        System.out.println(result); // [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

    }

    public static <T> List<T> math(List<T> list, UnaryOperator<T> uo) {
        List<T> result = new ArrayList<>();
        for (T t : list) {
            result.add(uo.apply(t));
        }
        return result;
    }

} 

输出

 [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] 

3.链式单运算器

Java8UnaryOperator3.java

 package com.mkyong;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.UnaryOperator;

public class Java8UnaryOperator3 {

    public static void main(String[] args) {

        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        List<Integer> result = math(list,
                x -> x * 2,
                x -> x + 1);

        System.out.println(result); // [3, 5, 7, 9, 11, 13, 15, 17, 19, 21]

    }

    public static <T> List<T> math(List<T> list,
                                   UnaryOperator<T> uo, UnaryOperator<T> uo2) {
        List<T> result = new ArrayList<>();
        for (T t : list) {
            result.add(uo.andThen(uo2).apply(t));
        }
        return result;
    }

} 

输出

 [3, 5, 7, 9, 11, 13, 15, 17, 19, 21] 

参考

Java 8 – ZonedDateTime examples

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-zoneddatetime-examples/

paris-time-zone

几个例子向你展示如何在不同国家之间转换时区。

1.马来西亚(KUL) ->日本(HND)

查看从马来西亚吉隆坡(UTC+08:00)到日本东京羽田(UTC+09:00)的航班信息

---Flight Detail---
Kuala Lumpur (KUL) -> Tokyo Haneda (HND)
Flight Duration : 7 hours

(KUL-Depart) 1430, 22 Aug 2016 ->  2230, 22 Aug 2016 (HND-Arrive)

日本东京比马来西亚吉隆坡快一小时

DifferentTimeZoneExample1.java

 package com.mkyong.timezone;

import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class DifferentTimeZoneExample1 {

    public static void main(String[] args) {

        DateTimeFormatter format = DateTimeFormatter.ofPattern("HHmm, dd MMM yyyy");

        LocalDateTime ldt = LocalDateTime.of(2016, Month.AUGUST, 22, 14, 30);
        System.out.println("LocalDateTime : " + format.format(ldt));

        //UTC+8
        ZonedDateTime klDateTime = ldt.atZone(ZoneId.of("Asia/Kuala_Lumpur"));
        System.out.println("Depart : " + format.format(klDateTime));

        //UTC+9 and flight duration = 7 hours
        ZonedDateTime japanDateTime = klDateTime.withZoneSameInstant(ZoneId.of("Asia/Tokyo")).plusHours(7);
        System.out.println("Arrive : " + format.format(japanDateTime));

        System.out.println("\n---Detail---");
        System.out.println("Depart : " + klDateTime);
        System.out.println("Arrive : " + japanDateTime);

    }

} 

输出

 LocalDateTime : 1430, 22 Aug 2016
Depart : 1430, 22 Aug 2016
Arrive : 2230, 22 Aug 2016

---Detail---
Depart : 2016-08-22T14:30+08:00[Asia/Kuala_Lumpur]
Arrive : 2016-08-22T22:30+09:00[Asia/Tokyo] 

2.法国,巴黎-> -05:00

另一个时区示例是从法国巴黎(UTC+02:00,DST)到硬编码(UTC-05:00)时区(如纽约)

---Flight Detail---
France, Paris -> UTC-05:00
Flight Duration : 8 hours 10 minutes

(Depart) 1430, 22 Aug 2016 ->  1540, 22 Aug 2016 (Arrive)

DifferentTimeZoneExample2.java

 package com.mkyong.timezone;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class DifferentTimeZoneExample2 {

    public static void main(String[] args) {

        DateTimeFormatter format = DateTimeFormatter.ofPattern("HHmm, dd MMM yyyy");

        //Convert String to LocalDateTime
        String date = "2016-08-22 14:30";
        LocalDateTime ldt = LocalDateTime.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
        System.out.println("LocalDateTime : " + format.format(ldt));

        //Paris, 2016 Apr-Oct = DST, UTC+2, other months UTC+1
        //UTC+2
        ZonedDateTime parisDateTime = ldt.atZone(ZoneId.of("Europe/Paris"));
        System.out.println("Depart : " + format.format(parisDateTime));

        //hard code a zoneoffset like this, UTC-5
        ZoneOffset nyOffSet = ZoneOffset.of("-05:00");
        ZonedDateTime nyDateTime = parisDateTime.withZoneSameInstant(nyOffSet).plusHours(8).plusMinutes(10);
        System.out.println("Arrive : " + format.format(nyDateTime));

        System.out.println("\n---Detail---");
        System.out.println("Depart : " + parisDateTime);
        System.out.println("Arrive : " + nyDateTime);

    }

} 

输出

 LocalDateTime : 1430, 22 Aug 2016
Depart : 1430, 22 Aug 2016
Arrive : 1540, 22 Aug 2016

---Detail---
Depart : 2016-08-22T14:30+02:00[Europe/Paris]
Arrive : 2016-08-22T15:40-05:00 

Daylight Saving Time (DST)
Paris, normally UTC+1 has DST (add one hour = UTC+2) from 27/mar to 30/Oct, 2016. Review the above output, the java.time is able to calculate and handle the DST correctly. ## 参考

  1. 维基百科–夏令时
  2. DateTimeFormatter JavaDoc
  3. ZoneddateTime JavaDoc
  4. 巴黎的时区
  5. 亚航-航班信息
  6. Java 8–将 Instant 转换为 ZonedDateTime
  7. Java–在时区之间转换日期和时间
  8. Java 8–如何将字符串转换为本地日期

dst java.time java8 timezone utc zoneddatetime zoneoffset

Java MongoDB:认证示例

原文:http://web.archive.org/web/20230101150211/http://www.mkyong.com/mongodb/java-authentication-access-to-mongodb/

默认情况下,MongoDB 运行在可信环境中(不需要使用用户名和密码进行身份验证)。在本教程中,我们将向您展示如何在安全模式下启动 MongoDB/启用身份验证,并连接 Java MongoDB 驱动程序。

1.在安全模式下启动 MongoDB

--auth选项启动 MongoDB,现在,MongoDB 需要用户名和密码来执行任何数据库/集合操作。

 mongod --auth 

后来,我们需要连接到数据库“testdb”,所以添加一个用户,以便稍后进行测试。

 > use admin
> db.addUser("admin","password")
> use testdb
> db.addUser("mkyong","password") 

要启用 MongoDB 认证,您必须首先将一个用户添加到特殊的“admin”数据库,详细指南请参考此 MongoDB 认证示例

2.Java + MongoDB 认证示例

如果 MongoDB 是在安全模式下启动的,下面的“插入”操作将不再有效,并提示“需要登录”的错误信息。

 Mongo mongo = new Mongo("localhost", 27017);
	DB db = mongo.getDB("testdb");

	DBCollection table = db.getCollection("user");

	BasicDBObject document = new BasicDBObject();
	document.put("name", "mkyong");
	table.insert(document); 
 com.mongodb.CommandResult$CommandFailure: command failed [getlasterror]: 
	{ "serverUsed" : "localhost/127.0.0.1:27017" , "errmsg" : "need to login" , "ok" : 0.0}

	at com.mongodb.CommandResult.getException(CommandResult.java:88)
	at com.mongodb.CommandResult.throwOnError(CommandResult.java:134)
	at com.mongodb.DBTCPConnector._checkWriteError(DBTCPConnector.java:142)
	at com.mongodb.DBTCPConnector.say(DBTCPConnector.java:183)
	at com.mongodb.DBTCPConnector.say(DBTCPConnector.java:155)
	at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:270)
	at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:226)
	at com.mongodb.DBCollection.insert(DBCollection.java:75)
	at com.mongodb.DBCollection.insert(DBCollection.java:59)
	at com.mongodb.DBCollection.insert(DBCollection.java:104)
	at com.mkyong.core.App.main(App.java:40) 

现在,使用db.authenticate()来执行认证,返回值 true =成功,false =失败。

 package com.mkyong.core;

import java.net.UnknownHostException;
import java.util.Date;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.Mongo;
import com.mongodb.MongoException;

/**
 * Java + MongoDB in Secure Mode
 * 
 */
public class JavaMongoDBAuthExample {
   public static void main(String[] args) {

    try {

	Mongo mongo = new Mongo("localhost", 27017);
	DB db = mongo.getDB("testdb");

	boolean auth = db.authenticate("testdb", "password".toCharArray());
	if (auth) {

		DBCollection table = db.getCollection("user");

		BasicDBObject document = new BasicDBObject();
		document.put("name", "mkyong");
		table.insert(document);

		System.out.println("Login is successful!");
	} else {
		System.out.println("Login is failed!");
	}
	System.out.println("Done");

    } catch (UnknownHostException e) {
	e.printStackTrace();
    } catch (MongoException e) {
	e.printStackTrace();
    }
  }
} 

参考

  1. Java MongoDB 认证示例
  2. JIRA–db . authenticate()应该使用字符[]作为密码
  3. MongoDB Java 认证示例
  4. MongoDB 安全实践和管理

authentication mongodb

Java–检查数组是否包含某个值?

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-check-if-array-contains-a-certain-value/

Java 示例检查数组(字符串或原始类型)是否包含特定值,用 Java 8 流 API 更新。

1.字符串数组

1.1 检查字符串数组是否包含某个值“A”。

StringArrayExample1.java

 package com.mkyong.core;

import java.util.Arrays;
import java.util.List;

public class StringArrayExample1 {

    public static void main(String[] args) {

        String[] alphabet = new String[]{"A", "B", "C"};

        // Convert String Array to List
        List<String> list = Arrays.asList(alphabet);

        if(list.contains("A")){
            System.out.println("Hello A");
        }

    }

} 

输出

 Hello A 

在 Java 8 中,您可以这样做:

 // Convert to stream and test it
	boolean result = Arrays.stream(alphabet).anyMatch("A"::equals);
	if (result) {
		System.out.println("Hello A");
	} 

1.2 检查字符串数组是否包含多个值的示例:

StringArrayExample2.java

 package com.mkyong.core;

import java.util.Arrays;
import java.util.List;

public class StringArrayExample2 {

    public static void main(String[] args) {

        String[] alphabet = new String[]{"A", "C"};

        // Convert String Array to List
        List<String> list = Arrays.asList(alphabet);

        // A or B
        if (list.contains("A") || list.contains("B")) {
            System.out.println("Hello A or B");
        }

        // A and B
        if (list.containsAll(Arrays.asList("A", "B"))) {
            System.out.println("Hello A and B");
        }

        // A and C
        if (list.containsAll(Arrays.asList("A", "C"))) {
            System.out.println("Hello A and C");
        }

    }

} 

输出

 Hello A or B
Hello A and C 

2.原始数组

2.1 对于int[]这样的基元数组,需要手动循环测试条件:

PrimitiveArrayExample1.java

 package com.mkyong.core;

import java.util.Arrays;
import java.util.List;

public class PrimitiveArrayExample1 {

    public static void main(String[] args) {

        int[] number = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

        if(contains(number, 2)){
            System.out.println("Hello 2");
        }

    }

    public static boolean contains(final int[] array, final int v) {

        boolean result = false;

        for(int i : array){
            if(i == v){
                result = true;
                break;
            }
        }

        return result;
    }

} 

输出

 Hello 2 

2.2 有了 Java 8,编码就简单多了~

ArrayExample1.java

 package com.mkyong.core;

import java.util.stream.IntStream;
import java.util.stream.LongStream;

public class TestDate {

    public static void main(String[] args) {

        int[] number = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

        //Java 8
        boolean result = IntStream.of(number).anyMatch(x -> x == 4);

        if (result) {
            System.out.println("Hello 4");
        } else {
            System.out.println("Where is number 4?");
        }

        long[] lNumber = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

        boolean result2 = LongStream.of(lNumber).anyMatch(x -> x == 10);

        if (result2) {
            System.out.println("Hello 10");
        } else {
            System.out.println("Where is number 10?");
        }

    }

} 

输出

 Hello 4
Hello 10 

Note
To check if a primitive array contains multiple values, convert the array into a List and compare it like example 1.2 above.

引用

  1. IntStream JavaDoc
  2. 阵列。aslist JavaDoc

标签:arrayIntStreamjava8stream

Java–检查日期是否超过 30 天或 6 个月

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-check-if-the-date-is-older-than-6-months/

本文展示了 Java 8 和遗留日期时间 API 示例,以检查日期是否比当前日期早 30 天或 6 个月。

1。Java 8 isBefore()

首先减去当前日期,然后使用isBefore()检查某个日期是否比当前日期早一段时间。

1.1 此示例检查一个日期是否比当前日期早 6 个月。

JavaMinusMonth.java

 package com.mkyong.app;

import java.time.LocalDate;

public class JavaMinusMonths {

  public static void main(String[] args) {

      LocalDate currentDate = LocalDate.now();
      LocalDate currentDateMinus6Months = currentDate.minusMonths(6);

      // 2021-03-26
      System.out.println("currentDate: " + currentDate);

      // 2020-09-26
      System.out.println("currentDateMinus6Months : " + currentDateMinus6Months);

      LocalDate date1 = LocalDate.of(2019, 8, 23);
      System.out.println("\ndate1 : " + date1);
      if (date1.isBefore(currentDateMinus6Months)) {
          System.out.println("6 months older than current date!");
      }

  }
} 

输出

Terminal

 currentDate: 2021-03-26
currentDateMinus6Months : 2020-09-26

date1 : 2019-08-23
6 months older than current date! 

1.2 此示例检查一个日期是否比当前日期早 30 天。

JavaMinusDays.java

 package com.mkyong.app;

import java.time.LocalDate;

public class JavaMinusDays {

  public static void main(String[] args) {

      LocalDate currentDate = LocalDate.now();
      LocalDate currentDateMinus30Days = currentDate.minusDays(30);

      // 2021-03-26
      System.out.println("currentDate: " + currentDate);

      // 2020-09-26
      System.out.println("currentDateMinus30Days : " + currentDateMinus30Days);

      LocalDate date1 = LocalDate.of(2019, 8, 23);
      System.out.println("\ndate1 : " + date1);
      if (date1.isBefore(currentDateMinus30Days)) {
          System.out.println("30 months older than current date!");
      }

  }
} 

2。Java 8 计时单位。{UNIT}。()之间

大多数新的 Java 8 日期和时间 API 都是通过Temporal接口实现的,例如LocalDateLocalDateTimeZonedDateTime等。我们可以使用ChronoUnit.{UNIT}.between来检查两个日期或Temporal对象之间的差异。

2.1 审查以下ChronoUnit.{UNIT}.between方法:

 ChronoUnit.NANOS.between(Temporal t1, Temporal t2)
ChronoUnit.MICROS.between(Temporal t1, Temporal t2)
ChronoUnit.MILLIS.between(Temporal t1, Temporal t2)
ChronoUnit.SECONDS.between(Temporal t1, Temporal t2)
ChronoUnit.MINUTES.between(Temporal t1, Temporal t2)
ChronoUnit.HOURS.between(Temporal t1, Temporal t2)
ChronoUnit.HALF_DAYS.between(Temporal t1, Temporal t2)
ChronoUnit.DAYS.between(Temporal t1, Temporal t2)
ChronoUnit.WEEKS.between(Temporal t1, Temporal t2)
ChronoUnit.MONTHS.between(Temporal t1, Temporal t2)
ChronoUnit.YEARS.between(Temporal t1, Temporal t2)
ChronoUnit.DECADES.between(Temporal t1, Temporal t2)
ChronoUnit.CENTURIES.between(Temporal t1, Temporal t2)
ChronoUnit.MILLENNIA.between(Temporal t1, Temporal t2)
ChronoUnit.ERAS.between(Temporal t1, Temporal t2) 

2.2 这个例子使用ChronoUnit.MONTHS.between来检查一个日期是否比当前日期早 6 个月。

JavaChronoUnit1.java

 package com.mkyong.app;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

public class JavaChronoUnit1 {

  public static void main(String[] args) {

      LocalDate now = LocalDate.now();    // 2021-03-26
      System.out.println("now: " + now);

      LocalDate date1 = LocalDate.of(2019, 9, 25);

      long months = ChronoUnit.MONTHS.between(now, date1);
      System.out.println(date1);
      System.out.println(months);

      if (months <= -6) {
          System.out.println("6 months older than current date!");
      }

      LocalDate date2 = LocalDate.of(2020, 9, 26);
      long months2 = ChronoUnit.MONTHS.between(now, date2);
      System.out.println(date2);
      System.out.println(months2);
      if (months2 <= -6) {
          System.out.println("6 months older than current date!");
      }

  }
} 

输出

Terminal

 now: 2021-03-26

2019-09-25
-18
6 months older than current date!

2020-09-26
-6
6 months older than current date! 

2.3 这个例子使用ChronoUnit.DAYS.between来检查一个日期是否比当前日期早 30 天。

JavaChronoUnit2.java

 package com.mkyong.app;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

public class JavaChronoUnit2 {

  public static void main(String[] args) {

      LocalDate now = LocalDate.now();    // 2021-03-26
      System.out.println("now: " + now);

      LocalDate date1 = LocalDate.of(2019, 9, 25);

      long day1 = ChronoUnit.DAYS.between(now, date1);
      System.out.println(date1);
      System.out.println(day1);

      if (day1 <= -30) {
          System.out.println("30 days older than current date!");
      }

      LocalDate date2 = LocalDate.of(2021, 2, 25);
      long day2 = ChronoUnit.DAYS.between(now, date2);
      System.out.println(date2);
      System.out.println(day2);
      if (day2 <= -30) {
          System.out.println("30 days older than current date!");
      }

  }
} 

输出

Terminal

 now: 2021-03-26

2019-09-25
-548
30 days older than current date!

2021-02-25
-29 

3。Java 8 Period.between()

3.1 阅读一个简单的java.time.Period例子,了解周期是如何工作的。

JavaPeriodExample.java

 package com.mkyong.app;

import java.time.LocalDate;
import java.time.Period;

public class JavaPeriodExample {

  public static void main(String[] args) {

      LocalDate date1 = LocalDate.of(2020, 2, 24);
      LocalDate date2 = LocalDate.of(2019, 8, 23);

      System.out.println(date1);  // 2020-02-24
      System.out.println(date2);  // 2019-08-23

      Period period = Period.between(date1, date2);
      String result = String.format("%d years, %d months, %d days",
              period.getYears(), period.getMonths(), period.getDays());

      System.out.println(result); // 0 years, -6 months, -1 days

      LocalDate date3 = LocalDate.of(2019, 1, 1);
      LocalDate date4 = LocalDate.of(2021, 3, 23);

      System.out.println(date3);  // 2019-01-01
      System.out.println(date4);  // 2021-03-23

      Period period2 = Period.between(date3, date4);
      String result2 = String.format("%d years, %d months, %d days",
              period2.getYears(), period2.getMonths(), period2.getDays());

      System.out.println(result2); // 2 years, 2 months, 22 days

  }

} 

输出

Terminal

 2020-02-24
2019-08-23
0 years, -6 months, -1 days
2019-01-01
2021-03-23
2 years, 2 months, 22 days 

3.2 此示例使用Period来检查LocalDate是否比当前日期大 6 个月。

JavaPeriodExample2.java

 package com.mkyong.app;

import java.time.LocalDate;
import java.time.Period;

public class JavaPeriodExample2 {

  public static void main(String[] args) {

      LocalDate date1 = LocalDate.of(2020, 9, 25);
      System.out.println("Is 6 months older? " + isOlderThanMonths(date1, 6));

      LocalDate date2 = LocalDate.of(2020, 9, 26);
      System.out.println("Is 6 months older? " + isOlderThanMonths(date2, 6));

      LocalDate date3 = LocalDate.of(2020, 10, 26);
      System.out.println("Is 6 months older? " + isOlderThanMonths(date3, 6));

      LocalDate date4 = LocalDate.of(2001, 10, 26);
      System.out.println("Is 6 months older? " + isOlderThanMonths(date4, 6));

  }

  static boolean isOlderThanMonths(final LocalDate date, final int months) {

      boolean result = false;

      LocalDate now = LocalDate.now();
      // period from now to date
      Period period = Period.between(now, date);

      System.out.println("\nNow: " + now);
      System.out.println("Date: " + date);
      System.out.printf("%d years, %d months, %d days%n",
              period.getYears(), period.getMonths(), period.getDays());

      if (period.getYears() < 0) {
          // if year is negative, 100% older than 6 months
          result = true;
      } else if (period.getYears() == 0) {
          if (period.getMonths() <= -months) {
              result = true;
          }
      }

      return result;

  }

} 

输出

Terminal

 Now: 2021-03-26

Date: 2020-09-25
0 years, -6 months, -1 days
Is 6 months older? true

Now: 2021-03-26
Date: 2020-09-26
0 years, -6 months, 0 days
Is 6 months older? true

Now: 2021-03-26
Date: 2020-10-26
0 years, -5 months, 0 days
Is 6 months older? false

Now: 2021-03-26
Date: 2001-10-26
-19 years, -5 months, 0 days
Is 6 months older? true 

4。传统日历和日期

4.1 本例检查java.util.Calendar是否比当前日期早 6 个月。

JavaCalendarExample.java

 package com.mkyong.app;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;

public class JavaCalendarExample {

  private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

  public static void main(String[] args) {

      Calendar sixMonthsAgo = Calendar.getInstance();
      // Current date
      // 2021-03-26
      System.out.println("now: " + sdf.format(sixMonthsAgo.getTime()));

      // old way to minus 6 months
      // 2020-09-26
      sixMonthsAgo.add(Calendar.MONTH, -6);
      System.out.println("sixMonthsAgo: " + sdf.format(sixMonthsAgo.getTime()));

      // 2019-06-10
      Calendar date1 = new GregorianCalendar(2020, Calendar.AUGUST, 10);
      System.out.println("date1: " + sdf.format(date1.getTime()));

      if (date1.before(sixMonthsAgo)) {
          System.out.println("6 months older than current date!");
      }

  }

} 

输出

Terminal

 now: 2021-03-26
sixMonthsAgo: 2020-09-26
date1: 2020-08-10
6 months older than current date! 

4.2 本例检查java.util.Date是否比当前日期早 30 天。

JavaDateExample.java

 package com.mkyong.app;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class JavaDateExample {

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    public static void main(String[] args) throws ParseException {

        Date today = new Date();
        System.out.println("now : " + sdf.format(today));         // 2021-03-26

        Calendar thirtyDaysAgo = Calendar.getInstance();
        thirtyDaysAgo.add(Calendar.DAY_OF_MONTH, -30);            // 2021-02-24

        // convert Calendar to Date
        Date thirtyDaysAgoDate = thirtyDaysAgo.getTime();
        System.out.println("thirtyDaysAgo : " + sdf.format(thirtyDaysAgoDate));

        Date date1 = sdf.parse("2019-12-31");
        if (date1.before(thirtyDaysAgoDate)) {
            System.out.println("30 days older than current date!");
        }

    }

} 

输出

Terminal

 now : 2021-03-26
thirtyDaysAgo : 2021-02-24
30 days older than current date! 

5。参考文献

Java–将数组转换为数组列表

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-convert-array-to-arraylist/

在 Java 中,我们可以使用new ArrayList<>(Arrays.asList(array))将一个Array转换成一个ArrayList

ArrayExample1.java

 package com.mkyong;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ArrayExample1 {

    public static void main(String[] args) {

        String[] str = {"A", "B", "C"};

        List<String> list = new ArrayList<>(Arrays.asList(str));

        list.add("D");

        list.forEach(x -> System.out.println(x));

    }
} 

输出

 A
B
C
D 

Arrays.asList返回一个固定的或不可修改的列表,如果我们修改列表,UnsupportedOperationException将被抛出。

 List<String> list = Arrays.asList(str); 				 // unmodifiable list

	list.add("D"); 		// java.lang.UnsupportedOperationException

	List<String> list2 = new ArrayList<>(Arrays.asList(str)); // modifiable list

	list2.add("D"); 	// ok 

1.Java 8 流

ArrayExample2.java

 package com.mkyong;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class ArrayExample2 {

    public static void main(String[] args) {

        String[] str = {"A", "B", "C"};

        ArrayList<String> list1 = Stream.of(str).collect(Collectors.toCollection(ArrayList::new));
        list1.add("D");
        list1.forEach(x -> System.out.println(x));

        List<String> list2 = Stream.of(str).collect(Collectors.toList());
        list2.add("D");
        list2.forEach(x -> System.out.println(x));

    }
} 

输出

 A
B
C
D
A
B
C
D 

2.Java 9–list . of()

P.S List.of返回固定或不可修改列表

ArrayExample3.java

 package com.mkyong;

import java.util.ArrayList;
import java.util.List;

public class ArrayExample3 {

    public static void main(String[] args) {

        String[] str = {"A", "B", "C"};

        // Java 9
        List<String> list = new ArrayList<>(List.of("A", "B", "C"));

        list.add("D");

        list.forEach(x -> System.out.println(x));

    }
} 

输出

 A
B
C
D 

参考

Java–将逗号分隔的字符串转换为列表

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-convert-comma-separated-string-to-a-list/

这个 Java 例子向你展示了如何将一个逗号分隔的字符串转换成一个列表,反之亦然。

1.要列出的逗号分隔的字符串

TestApp1.java

 package com.mkyong.utils;

import java.util.Arrays;
import java.util.List;

public class TestApp1 {

    public static void main(String[] args) {

        String alpha = "A, B, C, D";

		//Remove whitespace and split by comma 
        List<String> result = Arrays.asList(alpha.split("\\s*,\\s*"));

        System.out.println(result);
    }

} 

输出

 [A, B, C, D] 

2.列表为逗号分隔的字符串

不需要循环List,使用新的 Java 8 String.join

TestApp2.java

 package com.mkyong.utils;

import java.util.Arrays;
import java.util.List;

public class TestApp2 {

    public static void main(String[] args) {

        List<String> list = Arrays.asList("A", "B", "C", "D");

        String result = String.join(",", list);
        System.out.println(result);
    }

} 

输出

 A,B,C,D 

参考

  1. StringJoiner JavaDoc
  2. Java 8–string joiner 示例

Java–在时区之间转换日期和时间

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-convert-date-and-time-between-timezone/

timezone

在本教程中,我们将向您展示几个示例( ZonedDateTime (Java 8)DateCalendarJoda Time )来转换不同时区之间的日期和时间。

所有示例都将日期和时间从

 (UTC+8:00) Asia/Singapore - Singapore Time
Date : 22-1-2015 10:15:55 AM 

 (UTC-5:00) America/New_York - Eastern Standard Time
Date : 21-1-2015 09:15:55 PM 

Which to use?
For time zone, avoid both Date and Calendar

  1. 如果您使用的是> = 8 的 JDK,请使用新的java.time.*框架。
  2. 如果您使用 JDK < 8,请使用 Joda 时间。(新的 Java 8 java.time.*框架就是受这个库的启发)

1.ZonedDateTime

总是使用这个新的 Java 8 java.time.ZonedDateTime来表示包含时区的日期和时间。

ZonedDateTimeExample.java

 package com.mkyong.date;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class ZonedDateTimeExample {

    private static final String DATE_FORMAT = "dd-M-yyyy hh:mm:ss a";

    public static void main(String[] args) {

        String dateInString = "22-1-2015 10:15:55 AM";
        LocalDateTime ldt = LocalDateTime.parse(dateInString, DateTimeFormatter.ofPattern(DATE_FORMAT));

        ZoneId singaporeZoneId = ZoneId.of("Asia/Singapore");
        System.out.println("TimeZone : " + singaporeZoneId);

        //LocalDateTime + ZoneId = ZonedDateTime
        ZonedDateTime asiaZonedDateTime = ldt.atZone(singaporeZoneId);
        System.out.println("Date (Singapore) : " + asiaZonedDateTime);

        ZoneId newYokZoneId = ZoneId.of("America/New_York");
        System.out.println("TimeZone : " + newYokZoneId);

        ZonedDateTime nyDateTime = asiaZonedDateTime.withZoneSameInstant(newYokZoneId);
        System.out.println("Date (New York) : " + nyDateTime);

        DateTimeFormatter format = DateTimeFormatter.ofPattern(DATE_FORMAT);
        System.out.println("\n---DateTimeFormatter---");
        System.out.println("Date (Singapore) : " + format.format(asiaZonedDateTime));
        System.out.println("Date (New York) : " + format.format(nyDateTime));

    }

} 

输出

 TimeZone : Asia/Singapore
Date (Singapore) : 2015-01-22T10:15:55+08:00[Asia/Singapore]
TimeZone : America/New_York
Date (New York) : 2015-01-21T21:15:55-05:00[America/New_York]

---DateTimeFormatter---
Date (Singapore) : 22-1-2015 10:15:55 AM
Date (New York) : 21-1-2015 09:15:55 PM 

Note
Refer to this ZonedDateTime tutorial for more time zone, custom offset and daylight saving time (DST) examples.

2.日期

Note
The java.util.Date has no concept of time zone, and only represents the number of seconds passed since the Unix epoch time – 1970-01-01T00:00:00Z. But, if you print the Date object directly, the Date object will be always printed with the default system time zone. Check the Date.toString() source code.

2.1 将时区设置为DateFormat并格式化java.util.Date

 SimpleDateFormat sdfAmerica = new SimpleDateFormat("dd-M-yyyy hh:mm:ss a");
sdfAmerica.setTimeZone(TimeZone.getTimeZone("America/New_York"));
String sDateInAmerica = sdfAmerica.format(date); 

2.2 完整示例

DateExample.java

 package com.mkyong.date;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class DateExample {

    private static final String DATE_FORMAT = "dd-M-yyyy hh:mm:ss a";

    public static void main(String[] args) throws ParseException {

        SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT);

        String dateInString = "22-01-2015 10:15:55 AM";
        Date date = formatter.parse(dateInString);
        TimeZone tz = TimeZone.getDefault();

        // From TimeZone Asia/Singapore
        System.out.println("TimeZone : " + tz.getID() + " - " + tz.getDisplayName());
        System.out.println("TimeZone : " + tz);
        System.out.println("Date (Singapore) : " + formatter.format(date));

        // To TimeZone America/New_York
        SimpleDateFormat sdfAmerica = new SimpleDateFormat(DATE_FORMAT);
        TimeZone tzInAmerica = TimeZone.getTimeZone("America/New_York");
        sdfAmerica.setTimeZone(tzInAmerica);

        String sDateInAmerica = sdfAmerica.format(date); // Convert to String first
        Date dateInAmerica = formatter.parse(sDateInAmerica); // Create a new Date object

        System.out.println("\nTimeZone : " + tzInAmerica.getID() + " - " + tzInAmerica.getDisplayName());
        System.out.println("TimeZone : " + tzInAmerica);
        System.out.println("Date (New York) (String) : " + sDateInAmerica);
        System.out.println("Date (New York) (Object) : " + formatter.format(dateInAmerica));

    }

} 

输出

 TimeZone : Asia/Kuala_Lumpur - Malaysia Time
TimeZone : sun.util.calendar.ZoneInfo[id="Asia/Kuala_Lumpur",...]
Date (Singapore) : 22-1-2015 10:15:55 AM

TimeZone : America/New_York - Eastern Standard Time
TimeZone : sun.util.calendar.ZoneInfo[id="America/New_York",...]
Date (New York) (String) : 21-1-2015 09:15:55 PM
Date (New York) (Object) : 21-1-2015 09:15:55 PM 

3.日历

3.1 设置时区的日历示例:

 Calendar calendar = new GregorianCalendar();
	calendar.setTime(date);
	calendar.setTimeZone(tzInAmerica); 

一个超级常见的错误是像这样直接得到java.util.Date:

 //Wrong, it will display 22-1-2015 10:15:55 AM, time is still in the system default time zone!
	Date dateInAmerican = calendar.getTime()); 

在上面的示例中,无论您在日历中设置了什么时区,Date 对象总是使用默认的系统时区进行打印。(查看Date.toString()源代码)

3.2 正确的做法应该是用DateFormat来格式化:

 SimpleDateFormat sdfAmerica = new SimpleDateFormat("dd-M-yyyy hh:mm:ss a");
	TimeZone tzInAmerica = TimeZone.getTimeZone("America/New_York");
	sdfAmerica.setTimeZone(tzInAmerica);
	sdfAmerica.format(calendar.getTime()) 

或者通过calendar.get()获取日期:

 int year = calendar.get(Calendar.YEAR);
	int month = calendar.get(Calendar.MONTH); // Jan = 0, dec = 11
	int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
	int hour = calendar.get(Calendar.HOUR); // 12 hour clock
	int hourOfDay = calendar.get(Calendar.HOUR_OF_DAY); // 24 hour clock
	int minute = calendar.get(Calendar.MINUTE);
	int second = calendar.get(Calendar.SECOND);
	int ampm = calendar.get(Calendar.AM_PM); //0 = AM , 1 = PM 

3.3 完整示例

CalendarExample.java

 package com.mkyong.date;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;

public class CalendarExample {

    private static final String DATE_FORMAT = "dd-M-yyyy hh:mm:ss a";

    public static void main(String[] args) throws ParseException {

        SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT);

        String dateInString = "22-01-2015 10:15:55 AM";
        Date date = formatter.parse(dateInString);
        TimeZone tz = TimeZone.getDefault();

        // From TimeZone Asia/Singapore
        System.out.println("TimeZone : " + tz.getID() + " - " + tz.getDisplayName());
        System.out.println("TimeZone : " + tz);
        System.out.println("Date (Singapore) : " + formatter.format(date));

        // To TimeZone America/New_York
        SimpleDateFormat sdfAmerica = new SimpleDateFormat(DATE_FORMAT);
        TimeZone tzInAmerica = TimeZone.getTimeZone("America/New_York");
        sdfAmerica.setTimeZone(tzInAmerica);

        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.setTimeZone(tzInAmerica);

        System.out.println("\nTimeZone : " + tzInAmerica.getID() + " - " + tzInAmerica.getDisplayName());
        System.out.println("TimeZone : " + tzInAmerica);

        //Wrong! It will print the date with the system default time zone
        System.out.println("Date (New York) (Wrong!): " + calendar.getTime());

        //Correct! need formatter
        System.out.println("Date (New York) (Correct!) : " + sdfAmerica.format(calendar.getTime()));

        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH); // Jan = 0, dec = 11
        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        int hour = calendar.get(Calendar.HOUR); // 12 hour clock
        int hourOfDay = calendar.get(Calendar.HOUR_OF_DAY); // 24 hour clock
        int minute = calendar.get(Calendar.MINUTE);
        int second = calendar.get(Calendar.SECOND);
        int ampm = calendar.get(Calendar.AM_PM); //0 = AM , 1 = PM

        //Correct
        System.out.println("\nyear \t\t: " + year);
        System.out.println("month \t\t: " + month + 1);
        System.out.println("dayOfMonth \t: " + dayOfMonth);
        System.out.println("hour \t\t: " + hour);
        System.out.println("minute \t\t: " + minute);
        System.out.println("second \t\t: " + second);
        System.out.println("ampm \t\t: " + ampm);

    }

} 

输出

 TimeZone : Asia/Kuala_Lumpur - Malaysia Time
TimeZone : sun.util.calendar.ZoneInfo[id="Asia/Kuala_Lumpur",...]
Date (Singapore) : 22-1-2015 10:15:55 AM

TimeZone : America/New_York - Eastern Standard Time
TimeZone : sun.util.calendar.ZoneInfo[id="America/New_York",...]]
Date (New York) (Wrong!): Thu Jan 22 10:15:55 MYT 2015
Date (New York) (Correct!) : 21-1-2015 09:15:55 PM

year 		: 2015
month 		: 01
dayOfMonth 	: 21
hour 		: 9
minute 		: 15
second 		: 55
ampm 		: 1 

4.Joda 时间

4.1 设置时区的 Joda 时间示例:

 DateTime dt = new DateTime(date);
	DateTimeZone dtZone = DateTimeZone.forID("America/New_York");
	DateTime dtus = dt.withZone(dtZone); 

同样,一个常见的错误是像这样直接获取日期,时区会丢失。

 //Output : 22-1-2015 10:15:55 AM
	Date dateInAmerica = dtus.toDate(); 

正确的做法是先转换成 Joda LocalDateTime

 //Output : 21-1-2015 09:15:55 PM
	Date dateInAmerica = dtus.toLocalDateTime().toDate(); 

4.2 完整示例

JodaTimeExample.java

 package com.mkyong.date;

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class JodaTimeExample {

    private static final String DATE_FORMAT = "dd-M-yyyy hh:mm:ss a";

    public static void main(String[] args) throws ParseException {

        SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT);

        String dateInString = "22-01-2015 10:15:55 AM";
        Date date = formatter.parse(dateInString);
        TimeZone tz = TimeZone.getDefault();

        // From TimeZone Asia/Singapore
        System.out.println("TimeZone : " + tz.getID() + " - " + tz.getDisplayName());
        System.out.println("TimeZone : " + tz);
        System.out.println("Date (Singapore) : " + formatter.format(date));

        // To TimeZone America/New_York
        SimpleDateFormat sdfAmerica = new SimpleDateFormat(DATE_FORMAT);
        DateTime dt = new DateTime(date);
        DateTimeZone dtZone = DateTimeZone.forID("America/New_York");
        DateTime dtus = dt.withZone(dtZone);
        TimeZone tzInAmerica = dtZone.toTimeZone();
        Date dateInAmerica = dtus.toLocalDateTime().toDate(); //Convert to LocalDateTime first

        sdfAmerica.setTimeZone(tzInAmerica);

        System.out.println("\nTimeZone : " + tzInAmerica.getID() + " - " + tzInAmerica.getDisplayName());
        System.out.println("TimeZone : " + tzInAmerica);
        System.out.println("DateTimeZone : " + dtZone);
        System.out.println("DateTime : " + dtus);

        System.out.println("dateInAmerica (Formatter) : " + formatter.format(dateInAmerica));
        System.out.println("dateInAmerica (Object) : " + dateInAmerica);

    }

} 

输出

 TimeZone : Asia/Kuala_Lumpur - Malaysia Time
TimeZone : sun.util.calendar.ZoneInfo[id="Asia/Kuala_Lumpur",...]
Date (Singapore) : 22-1-2015 10:15:55 AM

TimeZone : America/New_York - Eastern Standard Time
TimeZone : sun.util.calendar.ZoneInfo[id="America/New_York",...]
DateTimeZone : America/New_York
DateTime : 2015-01-21T21:15:55.000-05:00
dateInAmerica (Formatter) : 21-1-2015 09:15:55 PM
dateInAmerica (Object) : Wed Jan 21 21:15:55 MYT 2015 

用 Joda-time 2.9.4 测试的 P . S

参考

  1. 使用 JodaTime 在 Java 中操作日期和时间
  2. 世界时间服务器
  3. Java 8 – ZonedDateTime examples
  4. Java 8–将日期转换为本地日期和本地日期时间
  5. ZonedDateTime Javadoc
  6. 日历 JavaDoc
  7. 日期 JavaDoc
  8. 简单日期格式 JavaDoc

Java–将文件转换为路径

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-convert-file-to-path/

这篇文章展示了如何在 Java 中将一个文件转换成一个路径

java.io.File=>=

 // Convert File to Path
File file = new File("/home/mkyong/test/file.txt");
Path path = file.toPath(); 

java.nio.file.Path=>=

 // Convert Path to File
Path path = Paths.get("/home/mkyong/test/file.txt");
File file = path.toFile(); 

1.将文件转换为路径

在 Java 中,我们可以使用file.toPath()将一个File转换成一个Path

FileToPath.java

 package com.mkyong.io.howto;

import java.io.File;
import java.nio.file.Path;

public class FileToPath {

    public static void main(String[] args) {

        File file = new File("/home/mkyong/test/file.txt");

        // Java 1.7, convert File to Path
        Path path = file.toPath();

        System.out.println(path);

    }
} 

2.将路径转换为文件

在 Java 中,我们可以使用path.toFile()将一个Path转换成一个File

PathToFile.java

 package com.mkyong.io.howto;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;

public class PathToFile {

    public static void main(String[] args) {

        Path path = Paths.get("/home/mkyong/test/file.txt");

        // Convert Path to File
        File file = path.toFile();

        System.out.println(file);

    }
} 

下载源代码

$ git 克隆https://github.com/mkyong/core-java

$ cd java-io

参考

Java–将文件转换为字符串

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-convert-file-to-string/

在 Java 中,我们有很多方法将文件转换成字符串。

用于以后测试的文本文件。

c:\projects\app.log

 A
B
C
D
E 

1.Java 11–files . read string

java.nio.file.Files中增加了一个新的方法Files.readString,它使得从文件中读取字符串变得更加容易。

FileToString1.java

 package com.mkyong;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class FileToString1 {

    public static void main(String[] args) {

        String path = "c:\\projects\\app.log";

        try {

            // default StandardCharsets.UTF_8
            String content = Files.readString(Paths.get(path));
            System.out.println(content);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

} 

Terminal

 A
B
C
D
E 

2.Java 8–文件.行

将一个文件转换成一个Stream并连接它。

FileToString2.java

 package com.mkyong;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class FileToString2 {

    public static void main(String[] args) {

        String path = "c:\\projects\\app.log";

        try (Stream<String> lines = Files.lines(Paths.get(path))) {

            // Formatting like \r\n will be lost
            // String content = lines.collect(Collectors.joining());

            // UNIX \n, WIndows \r\n
            String content = lines.collect(Collectors.joining(System.lineSeparator()));
            System.out.println(content);

			// File to List
            //List<String> list = lines.collect(Collectors.toList());

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

} 

Terminal

 A
B
C
D
E 

3.Java 7–files . read all lines

将文件转换成List

FileExample3.java

 package com.mkyong;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

public class FileToString3 {

    public static void main(String[] args) {

        String path = "c:\\projects\\app.log";

        try {

            // default StandardCharsets.UTF_8
            // Java 8
            // List<String> content = Files.readAllLines(Paths.get(path));

			// Java 7
            List<String> content = Files.readAllLines(Paths.get(path), StandardCharsets.UTF_8);

            System.out.println(content);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

} 

输出

Terminal

 [A, B, C, D, E] 

4.Apache commons me(Apache 公用程式)

pom.xml

 <dependency>
		<groupId>commons-io</groupId>
		<artifactId>commons-io</artifactId>
		<version>2.6</version>
	</dependency> 

FileToString4.java

 package com.mkyong;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class FileToString4 {

    public static void main(String[] args) {

        String path = "c:\\projects\\app.log";

        try {
            String content = FileUtils.readFileToString(new File(path), StandardCharsets.UTF_8);
            System.out.println(content);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

} 

输出

Terminal

 A
B
C
D
E 

参考

Java–将字符串转换成 XML

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-convert-string-to-xml/

本文展示了如何使用 DOM parser 和 JDOM2 parser 在 Java 中将字符串转换成 XML 文档,并将 XML 文档转换回字符串。

1。将字符串转换为 XML (DOM 解析器)

这个例子展示了如何使用 DOM 解析器将字符串转换成 XML 文档,然后再转换成字符串。

ConvertStringToXmlDom.java

 package com.mkyong.xml.tips;

import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;

// DOM Parser
public class ConvertStringToXmlDom {

    final static String str = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
            "<company>\n" +
            "    <staff id=\"1001\">\n" +
            "        <name>mkyong</name>\n" +
            "        <role>support</role>\n" +
            "        <salary currency=\"USD\">5000</salary>\n" +
            "        <!-- for special characters like < &, need CDATA -->\n" +
            "        <bio><![CDATA[HTML tag <code>testing</code>]]></bio>\n" +
            "    </staff>\n" +
            "    <staff id=\"1002\">\n" +
            "        <name>yflow</name>\n" +
            "        <role>admin</role>\n" +
            "        <salary currency=\"EUR\">8000</salary>\n" +
            "        <bio><![CDATA[a & b]]></bio>\n" +
            "    </staff>\n" +
            "</company>";

    public static void main(String[] args) {

        // String to XML Document
        Document document = convertStringToXml(str);

        // XML Document to String
        String xml = convertXmlToString(document);

        System.out.println(xml);

    }

    private static String convertXmlToString(Document doc) {
        DOMSource domSource = new DOMSource(doc);
        StringWriter writer = new StringWriter();
        StreamResult result = new StreamResult(writer);
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = null;
        try {
            transformer = tf.newTransformer();
            transformer.transform(domSource, result);
        } catch (TransformerException e) {
            throw new RuntimeException(e);
        }
        return writer.toString();
    }

    private static Document convertStringToXml(String xmlString) {

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

        try {

            // optional, but recommended
            // process XML securely, avoid attacks like XML External Entities (XXE)
            dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);

            DocumentBuilder builder = dbf.newDocumentBuilder();

            Document doc = builder.parse(new InputSource(new StringReader(xmlString)));

            return doc;

        } catch (ParserConfigurationException | IOException | SAXException e) {
            throw new RuntimeException(e);
        }

    }

} 

输出

Terminal

 <?xml version="1.0" encoding="utf-8" standalone="no"?><company>
    <staff id="1001">
        <name>mkyong</name>
        <role>support</role>
        <salary currency="USD">5000</salary>
        <!-- for special characters like < &, need CDATA -->
        <bio><![CDATA[HTML tag <code>testing</code>]]></bio>
    </staff>
    <staff id="1002">
        <name>yflow</name>
        <role>admin</role>
        <salary currency="EUR">8000</salary>
        <bio><![CDATA[a & b]]></bio>
    </staff>
</company> 

2。将字符串转换为 XML (JDOM2 解析器)

这个例子展示了如何使用 JDOM2 解析器将字符串转换成 XML 文档,然后再转换回字符串。

pom.xml

 <dependency>
    <groupId>org.jdom</groupId>
    <artifactId>jdom2</artifactId>
    <version>2.0.6</version>
  </dependency> 

ConvertStringToXmlJDom2.java

 package com.mkyong.xml.tips;

import org.jdom2.Document;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;

import javax.xml.XMLConstants;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;

// JDOM2 Parser
public class ConvertStringToXmlJDom2 {

    final static String str = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
            "<company>\n" +
            "    <staff id=\"1001\">\n" +
            "        <name>mkyong</name>\n" +
            "        <role>support</role>\n" +
            "        <salary currency=\"USD\">5000</salary>\n" +
            "        <!-- for special characters like < &, need CDATA -->\n" +
            "        <bio><![CDATA[HTML tag <code>testing</code>]]></bio>\n" +
            "    </staff>\n" +
            "    <staff id=\"1002\">\n" +
            "        <name>yflow</name>\n" +
            "        <role>admin</role>\n" +
            "        <salary currency=\"EUR\">8000</salary>\n" +
            "        <bio><![CDATA[a & b]]></bio>\n" +
            "    </staff>\n" +
            "</company>";

    public static void main(String[] args) {

        // String to XML Document
        Document document = convertStringToXml(str);

        // XML Document to String
        String xml = convertXmlDocumentToString(document);

        System.out.println(xml);

    }

    private static String convertXmlDocumentToString(Document doc) {
        XMLOutputter xmlOutput = new XMLOutputter();
        xmlOutput.setFormat(Format.getPrettyFormat());

        StringWriter result = new StringWriter();
        try {
            xmlOutput.output(doc, result);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return result.toString();
    }

    private static Document convertStringToXml(String xmlString) {

        SAXBuilder sax = new SAXBuilder();

        // https://rules.sonarsource.com/java/RSPEC-2755
        // prevent xxe
        sax.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
        sax.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");

        try {

            Document doc = sax.build(new StringReader(xmlString));
            return doc;

        } catch (JDOMException | IOException e) {
            throw new RuntimeException(e);
        }

    }

} 

输出

Terminal

 <?xml version="1.0" encoding="UTF-8"?>
  <company>
    <staff id="1001">
      <name>mkyong</name>
      <role>support</role>
      <salary currency="USD">5000</salary>
      <!-- for special characters like < &, need CDATA -->
      <bio><![CDATA[HTML tag <code>testing</code>]]></bio>
    </staff>
    <staff id="1002">
      <name>yflow</name>
      <role>admin</role>
      <salary currency="EUR">8000</salary>
      <bio><![CDATA[a & b]]></bio>
    </staff>
  </company> 

3。下载源代码

$ git 克隆https://github.com/mkyong/core-java

$ cd java-xml

$ CD src/main/Java/com/mkyong/XML/tips/

4。参考文献

Java 日期和日历示例

原文:http://web.archive.org/web/20230101150211/https://www.mkyong.com/java/java-date-and-calendar-examples/

Calendar

本教程向您展示如何使用java.util.Datejava.util.Calendar

1.Java 日期示例

几个使用DateAPI 的例子。

示例 1.1–将日期转换为字符串。

 SimpleDateFormat sdf = new SimpleDateFormat("dd/M/yyyy");
	String date = sdf.format(new Date()); 
	System.out.println(date); //15/10/2013 

例 1.2–将字符串转换为日期。

 SimpleDateFormat sdf = new SimpleDateFormat("dd-M-yyyy hh:mm:ss");
	String dateInString = "31-08-1982 10:20:56";
	Date date = sdf.parse(dateInString);
	System.out.println(date); //Tue Aug 31 10:20:56 SGT 1982 

关于详细的日期和时间模式,请参考 this-simple date format JavaDoc

示例 1.3–获取当前日期时间

 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
	Date date = new Date();
	System.out.println(dateFormat.format(date)); //2013/10/15 16:16:39 

示例 1.4–将日历转换为日期

 Calendar calendar = Calendar.getInstance();
        Date date =  calendar.getTime(); 

2.Java 日历示例

几个使用CalendarAPI 的例子。

示例 2.1–获取当前日期时间

 SimpleDateFormat sdf = new SimpleDateFormat("yyyy MMM dd HH:mm:ss");	
	Calendar calendar = new GregorianCalendar(2013,0,31);
	System.out.println(sdf.format(calendar.getTime())); 

输出

 2013 Jan 31 00:00:00 

示例 2.2–简单日历示例

 SimpleDateFormat sdf = new SimpleDateFormat("yyyy MMM dd HH:mm:ss");	
	Calendar calendar = new GregorianCalendar(2013,1,28,13,24,56);

	int year       = calendar.get(Calendar.YEAR);
	int month      = calendar.get(Calendar.MONTH); // Jan = 0, dec = 11
	int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH); 
	int dayOfWeek  = calendar.get(Calendar.DAY_OF_WEEK);
	int weekOfYear = calendar.get(Calendar.WEEK_OF_YEAR);
	int weekOfMonth= calendar.get(Calendar.WEEK_OF_MONTH);

	int hour       = calendar.get(Calendar.HOUR);        // 12 hour clock
	int hourOfDay  = calendar.get(Calendar.HOUR_OF_DAY); // 24 hour clock
	int minute     = calendar.get(Calendar.MINUTE);
	int second     = calendar.get(Calendar.SECOND);
	int millisecond= calendar.get(Calendar.MILLISECOND);

	System.out.println(sdf.format(calendar.getTime()));

	System.out.println("year \t\t: " + year);
	System.out.println("month \t\t: " + month);
	System.out.println("dayOfMonth \t: " + dayOfMonth);
	System.out.println("dayOfWeek \t: " + dayOfWeek);
	System.out.println("weekOfYear \t: " + weekOfYear);
	System.out.println("weekOfMonth \t: " + weekOfMonth);

	System.out.println("hour \t\t: " + hour);
	System.out.println("hourOfDay \t: " + hourOfDay);
	System.out.println("minute \t\t: " + minute);
	System.out.println("second \t\t: " + second);
	System.out.println("millisecond \t: " + millisecond); 

输出

 2013 Feb 28 13:24:56
year 		: 2013
month 		: 1
dayOfMonth 	: 28
dayOfWeek 	: 5
weekOfYear 	: 9
weekOfMonth     : 5
hour 		: 1
hourOfDay 	: 13
minute 		: 24
second 		: 56
millisecond     : 0 

例 2.3–手动设置日期。

 SimpleDateFormat sdf = new SimpleDateFormat("yyyy MMM dd HH:mm:ss");	

	Calendar calendar = new GregorianCalendar(2013,1,28,13,24,56);	
	System.out.println("#1\. " + sdf.format(calendar.getTime()));

	//update a date
	calendar.set(Calendar.YEAR, 2014);
	calendar.set(Calendar.MONTH, 11);
	calendar.set(Calendar.MINUTE, 33);

	System.out.println("#2\. " + sdf.format(calendar.getTime())); 

输出

 #1\. 2013 Feb 28 13:24:56
#2\. 2014 Dec 28 13:33:56 

示例 2.4–增加或减少日期。

 SimpleDateFormat sdf = new SimpleDateFormat("yyyy MMM dd");	

	Calendar calendar = new GregorianCalendar(2013,10,28);	
	System.out.println("Date : " + sdf.format(calendar.getTime()));

	//add one month
	calendar.add(Calendar.MONTH, 1);
	System.out.println("Date : " + sdf.format(calendar.getTime()));

	//subtract 10 days
	calendar.add(Calendar.DAY_OF_MONTH, -10);
	System.out.println("Date : " + sdf.format(calendar.getTime())); 

输出

 Date : 2013 Nov 28
Date : 2013 Dec 28
Date : 2013 Dec 18 

示例 2.5–将日期转换为日历。

 SimpleDateFormat sdf = new SimpleDateFormat("dd-M-yyyy hh:mm:ss");
	String dateInString = "22-01-2015 10:20:56";
	Date date = sdf.parse(dateInString);

        Calendar calendar = Calendar.getInstance();
	calendar.setTime(date); 

参考

  1. 日历 JavaDoc
  2. 日期 JavaDoc
  3. Java–将字符串转换为日期
  4. 如何在 Java 中比较日期

Java–显示所有 ZoneId 及其 UTC 偏移量

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-display-all-zoneid-and-its-utc-offset/

一个 Java 8 示例,显示所有的 ZoneId 及其偏移小时和分钟。

P.S .用 Java 8 和 12 测试

1.显示 ZoneId 和偏移量

DisplayZoneAndOffSet.java

 package com.mkyong;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

public class DisplayZoneAndOffSet {

    public static final boolean SORT_BY_REGION = false;

    public static void main(String[] argv) {

        Map<String, String> sortedMap = new LinkedHashMap<>();

        Map<String, String> allZoneIdsAndItsOffSet = getAllZoneIdsAndItsOffSet();

        //sort map by key
        if (SORT_BY_REGION) {
            allZoneIdsAndItsOffSet.entrySet().stream()
                    .sorted(Map.Entry.comparingByKey())
                    .forEachOrdered(e -> sortedMap.put(e.getKey(), e.getValue()));
        } else {
            // sort by value, descending order
            allZoneIdsAndItsOffSet.entrySet().stream()
                    .sorted(Map.Entry.<String, String>comparingByValue().reversed())
                    .forEachOrdered(e -> sortedMap.put(e.getKey(), e.getValue()));
        }

        // print map
        sortedMap.forEach((k, v) ->
        {
            String out = String.format("%35s (UTC%s) %n", k, v);
            System.out.printf(out);
        });

        System.out.println("\nTotal Zone IDs " + sortedMap.size());

    }

    private static Map<String, String> getAllZoneIdsAndItsOffSet() {

        Map<String, String> result = new HashMap<>();

        LocalDateTime localDateTime = LocalDateTime.now();

        for (String zoneId : ZoneId.getAvailableZoneIds()) {

            ZoneId id = ZoneId.of(zoneId);

            // LocalDateTime -> ZonedDateTime
            ZonedDateTime zonedDateTime = localDateTime.atZone(id);

            // ZonedDateTime -> ZoneOffset
            ZoneOffset zoneOffset = zonedDateTime.getOffset();

            //replace Z to +00:00
            String offset = zoneOffset.getId().replaceAll("Z", "+00:00");

            result.put(id.toString(), offset);

        }

        return result;

    }

} 

输出

 Etc/GMT+12 (UTC-12:00) 
                  Pacific/Pago_Pago (UTC-11:00) 
                      Pacific/Samoa (UTC-11:00) 
                       Pacific/Niue (UTC-11:00) 
                           US/Samoa (UTC-11:00) 
                         Etc/GMT+11 (UTC-11:00) 
                     Pacific/Midway (UTC-11:00) 
                   Pacific/Honolulu (UTC-10:00) 
                  Pacific/Rarotonga (UTC-10:00) 
                     Pacific/Tahiti (UTC-10:00) 
                   Pacific/Johnston (UTC-10:00) 
                          US/Hawaii (UTC-10:00) 
                      SystemV/HST10 (UTC-10:00) 
                         Etc/GMT+10 (UTC-10:00) 
                  Pacific/Marquesas (UTC-09:30) 
                          Etc/GMT+9 (UTC-09:00) 
                    Pacific/Gambier (UTC-09:00) 
                       America/Atka (UTC-09:00) 
                       SystemV/YST9 (UTC-09:00) 
                       America/Adak (UTC-09:00) 
                        US/Aleutian (UTC-09:00) 
                          Etc/GMT+8 (UTC-08:00) 
                          US/Alaska (UTC-08:00) 
                     America/Juneau (UTC-08:00) 
                 America/Metlakatla (UTC-08:00) 
                    America/Yakutat (UTC-08:00) 
                   Pacific/Pitcairn (UTC-08:00) 
                      America/Sitka (UTC-08:00) 
                  America/Anchorage (UTC-08:00) 
                       SystemV/PST8 (UTC-08:00) 
                       America/Nome (UTC-08:00) 
                    SystemV/YST9YDT (UTC-08:00) 
                       Canada/Yukon (UTC-07:00) 
                     US/Pacific-New (UTC-07:00) 
                          Etc/GMT+7 (UTC-07:00) 
                         US/Arizona (UTC-07:00) 
               America/Dawson_Creek (UTC-07:00) 
                     Canada/Pacific (UTC-07:00) 
                            PST8PDT (UTC-07:00) 
                       SystemV/MST7 (UTC-07:00) 
                     America/Dawson (UTC-07:00) 
                   Mexico/BajaNorte (UTC-07:00) 
                    America/Tijuana (UTC-07:00) 
                    America/Creston (UTC-07:00) 
                 America/Hermosillo (UTC-07:00) 
               America/Santa_Isabel (UTC-07:00) 
                  America/Vancouver (UTC-07:00) 
                   America/Ensenada (UTC-07:00) 
                    America/Phoenix (UTC-07:00) 
                 America/Whitehorse (UTC-07:00) 
                America/Fort_Nelson (UTC-07:00) 
                    SystemV/PST8PDT (UTC-07:00) 
                America/Los_Angeles (UTC-07:00) 
                         US/Pacific (UTC-07:00) 
                America/El_Salvador (UTC-06:00) 
                  America/Guatemala (UTC-06:00) 
                     America/Belize (UTC-06:00) 
                    America/Managua (UTC-06:00) 
                America/Tegucigalpa (UTC-06:00) 
                          Etc/GMT+6 (UTC-06:00) 
                     Pacific/Easter (UTC-06:00) 
                     Mexico/BajaSur (UTC-06:00) 
                     America/Regina (UTC-06:00) 
                     America/Denver (UTC-06:00) 
                  Pacific/Galapagos (UTC-06:00) 
                America/Yellowknife (UTC-06:00) 
              America/Swift_Current (UTC-06:00) 
                     America/Inuvik (UTC-06:00) 
                   America/Mazatlan (UTC-06:00) 
                      America/Boise (UTC-06:00) 
                 America/Costa_Rica (UTC-06:00) 
                            MST7MDT (UTC-06:00) 
                       SystemV/CST6 (UTC-06:00) 
                  America/Chihuahua (UTC-06:00) 
                    America/Ojinaga (UTC-06:00) 
                 Chile/EasterIsland (UTC-06:00) 
                        US/Mountain (UTC-06:00) 
                   America/Edmonton (UTC-06:00) 
                    Canada/Mountain (UTC-06:00) 
              America/Cambridge_Bay (UTC-06:00) 
                             Navajo (UTC-06:00) 
                    SystemV/MST7MDT (UTC-06:00) 
                Canada/Saskatchewan (UTC-06:00) 
                   America/Shiprock (UTC-06:00) 
                     America/Panama (UTC-05:00) 
                    America/Chicago (UTC-05:00) 
                   America/Eirunepe (UTC-05:00) 
                          Etc/GMT+5 (UTC-05:00) 
                     Mexico/General (UTC-05:00) 
                 America/Porto_Acre (UTC-05:00) 
                  America/Guayaquil (UTC-05:00) 
               America/Rankin_Inlet (UTC-05:00) 
                         US/Central (UTC-05:00) 
                America/Rainy_River (UTC-05:00) 
               America/Indiana/Knox (UTC-05:00) 
        America/North_Dakota/Beulah (UTC-05:00) 
                  America/Monterrey (UTC-05:00) 
                    America/Jamaica (UTC-05:00) 
                   America/Atikokan (UTC-05:00) 
              America/Coral_Harbour (UTC-05:00) 
        America/North_Dakota/Center (UTC-05:00) 
                     America/Cayman (UTC-05:00) 
          America/Indiana/Tell_City (UTC-05:00) 
                America/Mexico_City (UTC-05:00) 
                  America/Matamoros (UTC-05:00) 
                            CST6CDT (UTC-05:00) 
                    America/Knox_IN (UTC-05:00) 
                     America/Bogota (UTC-05:00) 
                  America/Menominee (UTC-05:00) 
                   America/Resolute (UTC-05:00) 
                       SystemV/EST5 (UTC-05:00) 
                     Canada/Central (UTC-05:00) 
                        Brazil/Acre (UTC-05:00) 
                     America/Cancun (UTC-05:00) 
                       America/Lima (UTC-05:00) 
             America/Bahia_Banderas (UTC-05:00) 
                  US/Indiana-Starke (UTC-05:00) 
                 America/Rio_Branco (UTC-05:00) 
                    SystemV/CST6CDT (UTC-05:00) 
                            Jamaica (UTC-05:00) 
                     America/Merida (UTC-05:00) 
     America/North_Dakota/New_Salem (UTC-05:00) 
                   America/Winnipeg (UTC-05:00) 
                     America/Cuiaba (UTC-04:00) 
                    America/Marigot (UTC-04:00) 
         America/Indiana/Petersburg (UTC-04:00) 
                  Chile/Continental (UTC-04:00) 
                 America/Grand_Turk (UTC-04:00) 
                               Cuba (UTC-04:00) 
                          Etc/GMT+4 (UTC-04:00) 
                     America/Manaus (UTC-04:00) 
                 America/Fort_Wayne (UTC-04:00) 
                  America/St_Thomas (UTC-04:00) 
                   America/Anguilla (UTC-04:00) 
                     America/Havana (UTC-04:00) 
                        US/Michigan (UTC-04:00) 
                   America/Barbados (UTC-04:00) 
                 America/Louisville (UTC-04:00) 
                    America/Curacao (UTC-04:00) 
                     America/Guyana (UTC-04:00) 
                 America/Martinique (UTC-04:00) 
                America/Puerto_Rico (UTC-04:00) 
              America/Port_of_Spain (UTC-04:00) 
                       SystemV/AST4 (UTC-04:00) 
              America/Indiana/Vevay (UTC-04:00) 
          America/Indiana/Vincennes (UTC-04:00) 
                 America/Kralendijk (UTC-04:00) 
                    America/Antigua (UTC-04:00) 
               America/Indianapolis (UTC-04:00) 
                    America/Iqaluit (UTC-04:00) 
                 America/St_Vincent (UTC-04:00) 
        America/Kentucky/Louisville (UTC-04:00) 
                   America/Dominica (UTC-04:00) 
                   America/Asuncion (UTC-04:00) 
                            EST5EDT (UTC-04:00) 
                     America/Nassau (UTC-04:00) 
        America/Kentucky/Monticello (UTC-04:00) 
                        Brazil/West (UTC-04:00) 
                      America/Aruba (UTC-04:00) 
       America/Indiana/Indianapolis (UTC-04:00) 
                   America/Santiago (UTC-04:00) 
                     America/La_Paz (UTC-04:00) 
                America/Thunder_Bay (UTC-04:00) 
            America/Indiana/Marengo (UTC-04:00) 
               America/Blanc-Sablon (UTC-04:00) 
              America/Santo_Domingo (UTC-04:00) 
                         US/Eastern (UTC-04:00) 
                     Canada/Eastern (UTC-04:00) 
             America/Port-au-Prince (UTC-04:00) 
              America/St_Barthelemy (UTC-04:00) 
                    America/Nipigon (UTC-04:00) 
                    US/East-Indiana (UTC-04:00) 
                   America/St_Lucia (UTC-04:00) 
                 America/Montserrat (UTC-04:00) 
              America/Lower_Princes (UTC-04:00) 
                    America/Detroit (UTC-04:00) 
                    America/Tortola (UTC-04:00) 
                America/Porto_Velho (UTC-04:00) 
               America/Campo_Grande (UTC-04:00) 
                     America/Virgin (UTC-04:00) 
                America/Pangnirtung (UTC-04:00) 
                   America/Montreal (UTC-04:00) 
            America/Indiana/Winamac (UTC-04:00) 
                  America/Boa_Vista (UTC-04:00) 
                    America/Grenada (UTC-04:00) 
                   America/New_York (UTC-04:00) 
                   America/St_Kitts (UTC-04:00) 
                    America/Caracas (UTC-04:00) 
                 America/Guadeloupe (UTC-04:00) 
                    America/Toronto (UTC-04:00) 
                    SystemV/EST5EDT (UTC-04:00) 
        America/Argentina/Catamarca (UTC-03:00) 
                    Canada/Atlantic (UTC-03:00) 
          America/Argentina/Cordoba (UTC-03:00) 
                  America/Araguaina (UTC-03:00) 
            America/Argentina/Salta (UTC-03:00) 
                          Etc/GMT+3 (UTC-03:00) 
                 America/Montevideo (UTC-03:00) 
                        Brazil/East (UTC-03:00) 
          America/Argentina/Mendoza (UTC-03:00) 
     America/Argentina/Rio_Gallegos (UTC-03:00) 
                  America/Catamarca (UTC-03:00) 
                    America/Cordoba (UTC-03:00) 
                  America/Sao_Paulo (UTC-03:00) 
            America/Argentina/Jujuy (UTC-03:00) 
                    America/Cayenne (UTC-03:00) 
                     America/Recife (UTC-03:00) 
               America/Buenos_Aires (UTC-03:00) 
                 America/Paramaribo (UTC-03:00) 
                    America/Moncton (UTC-03:00) 
                    America/Mendoza (UTC-03:00) 
                   America/Santarem (UTC-03:00) 
                   Atlantic/Bermuda (UTC-03:00) 
                     America/Maceio (UTC-03:00) 
                   Atlantic/Stanley (UTC-03:00) 
                    America/Halifax (UTC-03:00) 
                 Antarctica/Rothera (UTC-03:00) 
         America/Argentina/San_Luis (UTC-03:00) 
          America/Argentina/Ushuaia (UTC-03:00) 
                  Antarctica/Palmer (UTC-03:00) 
               America/Punta_Arenas (UTC-03:00) 
                  America/Glace_Bay (UTC-03:00) 
                  America/Fortaleza (UTC-03:00) 
                      America/Thule (UTC-03:00) 
         America/Argentina/La_Rioja (UTC-03:00) 
                      America/Belem (UTC-03:00) 
                      America/Jujuy (UTC-03:00) 
                      America/Bahia (UTC-03:00) 
                  America/Goose_Bay (UTC-03:00) 
         America/Argentina/San_Juan (UTC-03:00) 
   America/Argentina/ComodRivadavia (UTC-03:00) 
          America/Argentina/Tucuman (UTC-03:00) 
                    America/Rosario (UTC-03:00) 
                    SystemV/AST4ADT (UTC-03:00) 
     America/Argentina/Buenos_Aires (UTC-03:00) 
                   America/St_Johns (UTC-02:30) 
                Canada/Newfoundland (UTC-02:30) 
                   America/Miquelon (UTC-02:00) 
                          Etc/GMT+2 (UTC-02:00) 
                    America/Godthab (UTC-02:00) 
                    America/Noronha (UTC-02:00) 
                   Brazil/DeNoronha (UTC-02:00) 
             Atlantic/South_Georgia (UTC-02:00) 
                          Etc/GMT+1 (UTC-01:00) 
                Atlantic/Cape_Verde (UTC-01:00) 
                 Pacific/Kiritimati (UTC+14:00) 
                         Etc/GMT-14 (UTC+14:00) 
                    Pacific/Fakaofo (UTC+13:00) 
                  Pacific/Enderbury (UTC+13:00) 
                       Pacific/Apia (UTC+13:00) 
                  Pacific/Tongatapu (UTC+13:00) 
                         Etc/GMT-13 (UTC+13:00) 
                            NZ-CHAT (UTC+12:45) 
                    Pacific/Chatham (UTC+12:45) 
                  Pacific/Kwajalein (UTC+12:00) 
                 Antarctica/McMurdo (UTC+12:00) 
                     Pacific/Wallis (UTC+12:00) 
                       Pacific/Fiji (UTC+12:00) 
                   Pacific/Funafuti (UTC+12:00) 
                      Pacific/Nauru (UTC+12:00) 
                          Kwajalein (UTC+12:00) 
                                 NZ (UTC+12:00) 
                       Pacific/Wake (UTC+12:00) 
              Antarctica/South_Pole (UTC+12:00) 
                     Pacific/Tarawa (UTC+12:00) 
                   Pacific/Auckland (UTC+12:00) 
                     Asia/Kamchatka (UTC+12:00) 
                         Etc/GMT-12 (UTC+12:00) 
                        Asia/Anadyr (UTC+12:00) 
                     Pacific/Majuro (UTC+12:00) 
                     Pacific/Ponape (UTC+11:00) 
               Pacific/Bougainville (UTC+11:00) 
               Antarctica/Macquarie (UTC+11:00) 
                    Pacific/Pohnpei (UTC+11:00) 
                      Pacific/Efate (UTC+11:00) 
                    Pacific/Norfolk (UTC+11:00) 
                       Asia/Magadan (UTC+11:00) 
                     Pacific/Kosrae (UTC+11:00) 
                      Asia/Sakhalin (UTC+11:00) 
                     Pacific/Noumea (UTC+11:00) 
                         Etc/GMT-11 (UTC+11:00) 
                 Asia/Srednekolymsk (UTC+11:00) 
                Pacific/Guadalcanal (UTC+11:00) 
                Australia/Lord_Howe (UTC+10:30) 
                      Australia/LHI (UTC+10:30) 
                   Australia/Hobart (UTC+10:00) 
                        Pacific/Yap (UTC+10:00) 
                 Australia/Tasmania (UTC+10:00) 
               Pacific/Port_Moresby (UTC+10:00) 
                      Australia/ACT (UTC+10:00) 
                 Australia/Victoria (UTC+10:00) 
                      Pacific/Chuuk (UTC+10:00) 
               Australia/Queensland (UTC+10:00) 
                 Australia/Canberra (UTC+10:00) 
                   Australia/Currie (UTC+10:00) 
                       Pacific/Guam (UTC+10:00) 
                       Pacific/Truk (UTC+10:00) 
                      Australia/NSW (UTC+10:00) 
                   Asia/Vladivostok (UTC+10:00) 
                     Pacific/Saipan (UTC+10:00) 
          Antarctica/DumontDUrville (UTC+10:00) 
                   Australia/Sydney (UTC+10:00) 
                 Australia/Brisbane (UTC+10:00) 
                         Etc/GMT-10 (UTC+10:00) 
                      Asia/Ust-Nera (UTC+10:00) 
                Australia/Melbourne (UTC+10:00) 
                 Australia/Lindeman (UTC+10:00) 
                    Australia/North (UTC+09:30) 
               Australia/Yancowinna (UTC+09:30) 
                 Australia/Adelaide (UTC+09:30) 
              Australia/Broken_Hill (UTC+09:30) 
                    Australia/South (UTC+09:30) 
                   Australia/Darwin (UTC+09:30) 
                          Etc/GMT-9 (UTC+09:00) 
                      Pacific/Palau (UTC+09:00) 
                         Asia/Chita (UTC+09:00) 
                          Asia/Dili (UTC+09:00) 
                      Asia/Jayapura (UTC+09:00) 
                       Asia/Yakutsk (UTC+09:00) 
                     Asia/Pyongyang (UTC+09:00) 
                                ROK (UTC+09:00) 
                         Asia/Seoul (UTC+09:00) 
                      Asia/Khandyga (UTC+09:00) 
                              Japan (UTC+09:00) 
                         Asia/Tokyo (UTC+09:00) 
                    Australia/Eucla (UTC+08:45) 
                       Asia/Kuching (UTC+08:00) 
                     Asia/Chungking (UTC+08:00) 
                          Etc/GMT-8 (UTC+08:00) 
                    Australia/Perth (UTC+08:00) 
                         Asia/Macao (UTC+08:00) 
                         Asia/Macau (UTC+08:00) 
                    Asia/Choibalsan (UTC+08:00) 
                      Asia/Shanghai (UTC+08:00) 
                   Antarctica/Casey (UTC+08:00) 
                    Asia/Ulan_Bator (UTC+08:00) 
                     Asia/Chongqing (UTC+08:00) 
                   Asia/Ulaanbaatar (UTC+08:00) 
                        Asia/Taipei (UTC+08:00) 
                        Asia/Manila (UTC+08:00) 
                                PRC (UTC+08:00) 
                 Asia/Ujung_Pandang (UTC+08:00) 
                        Asia/Harbin (UTC+08:00) 
                          Singapore (UTC+08:00) 
                        Asia/Brunei (UTC+08:00) 
                     Australia/West (UTC+08:00) 
                     Asia/Hong_Kong (UTC+08:00) 
                      Asia/Makassar (UTC+08:00) 
                           Hongkong (UTC+08:00) 
                  Asia/Kuala_Lumpur (UTC+08:00) 
                       Asia/Irkutsk (UTC+08:00) 
                     Asia/Singapore (UTC+08:00) 
                     Asia/Pontianak (UTC+07:00) 
                          Etc/GMT-7 (UTC+07:00) 
                    Asia/Phnom_Penh (UTC+07:00) 
                   Asia/Novosibirsk (UTC+07:00) 
                   Antarctica/Davis (UTC+07:00) 
                         Asia/Tomsk (UTC+07:00) 
                       Asia/Jakarta (UTC+07:00) 
                       Asia/Barnaul (UTC+07:00) 
                   Indian/Christmas (UTC+07:00) 
                   Asia/Ho_Chi_Minh (UTC+07:00) 
                          Asia/Hovd (UTC+07:00) 
                       Asia/Bangkok (UTC+07:00) 
                     Asia/Vientiane (UTC+07:00) 
                  Asia/Novokuznetsk (UTC+07:00) 
                   Asia/Krasnoyarsk (UTC+07:00) 
                        Asia/Saigon (UTC+07:00) 
                        Asia/Yangon (UTC+06:30) 
                       Asia/Rangoon (UTC+06:30) 
                       Indian/Cocos (UTC+06:30) 
                       Asia/Kashgar (UTC+06:00) 
                          Etc/GMT-6 (UTC+06:00) 
                        Asia/Almaty (UTC+06:00) 
                         Asia/Dacca (UTC+06:00) 
                          Asia/Omsk (UTC+06:00) 
                         Asia/Dhaka (UTC+06:00) 
                      Indian/Chagos (UTC+06:00) 
                     Asia/Qyzylorda (UTC+06:00) 
                       Asia/Bishkek (UTC+06:00) 
                  Antarctica/Vostok (UTC+06:00) 
                        Asia/Urumqi (UTC+06:00) 
                        Asia/Thimbu (UTC+06:00) 
                       Asia/Thimphu (UTC+06:00) 
                     Asia/Kathmandu (UTC+05:45) 
                      Asia/Katmandu (UTC+05:45) 
                       Asia/Kolkata (UTC+05:30) 
                       Asia/Colombo (UTC+05:30) 
                      Asia/Calcutta (UTC+05:30) 
                         Asia/Aqtau (UTC+05:00) 
                          Etc/GMT-5 (UTC+05:00) 
                     Asia/Samarkand (UTC+05:00) 
                       Asia/Karachi (UTC+05:00) 
                 Asia/Yekaterinburg (UTC+05:00) 
                      Asia/Dushanbe (UTC+05:00) 
                    Indian/Maldives (UTC+05:00) 
                          Asia/Oral (UTC+05:00) 
                      Asia/Tashkent (UTC+05:00) 
                  Antarctica/Mawson (UTC+05:00) 
                        Asia/Aqtobe (UTC+05:00) 
                     Asia/Ashkhabad (UTC+05:00) 
                      Asia/Ashgabat (UTC+05:00) 
                        Asia/Atyrau (UTC+05:00) 
                   Indian/Kerguelen (UTC+05:00) 
                               Iran (UTC+04:30) 
                        Asia/Tehran (UTC+04:30) 
                         Asia/Kabul (UTC+04:30) 
                       Asia/Yerevan (UTC+04:00) 
                          Etc/GMT-4 (UTC+04:00) 
                         Asia/Dubai (UTC+04:00) 
                     Indian/Reunion (UTC+04:00) 
                   Indian/Mauritius (UTC+04:00) 
                     Europe/Saratov (UTC+04:00) 
                      Europe/Samara (UTC+04:00) 
                        Indian/Mahe (UTC+04:00) 
                          Asia/Baku (UTC+04:00) 
                        Asia/Muscat (UTC+04:00) 
                   Europe/Volgograd (UTC+04:00) 
                   Europe/Astrakhan (UTC+04:00) 
                       Asia/Tbilisi (UTC+04:00) 
                   Europe/Ulyanovsk (UTC+04:00) 
                          Asia/Aden (UTC+03:00) 
                     Africa/Nairobi (UTC+03:00) 
                    Europe/Istanbul (UTC+03:00) 
                          Etc/GMT-3 (UTC+03:00) 
                  Europe/Zaporozhye (UTC+03:00) 
                             Israel (UTC+03:00) 
                      Indian/Comoro (UTC+03:00) 
                   Antarctica/Syowa (UTC+03:00) 
                   Africa/Mogadishu (UTC+03:00) 
                   Europe/Bucharest (UTC+03:00) 
                      Africa/Asmera (UTC+03:00) 
                   Europe/Mariehamn (UTC+03:00) 
                      Asia/Istanbul (UTC+03:00) 
                    Europe/Tiraspol (UTC+03:00) 
                      Europe/Moscow (UTC+03:00) 
                    Europe/Chisinau (UTC+03:00) 
                    Europe/Helsinki (UTC+03:00) 
                        Asia/Beirut (UTC+03:00) 
                      Asia/Tel_Aviv (UTC+03:00) 
                    Africa/Djibouti (UTC+03:00) 
                  Europe/Simferopol (UTC+03:00) 
                       Europe/Sofia (UTC+03:00) 
                          Asia/Gaza (UTC+03:00) 
                      Africa/Asmara (UTC+03:00) 
                        Europe/Riga (UTC+03:00) 
                       Asia/Baghdad (UTC+03:00) 
                      Asia/Damascus (UTC+03:00) 
               Africa/Dar_es_Salaam (UTC+03:00) 
                 Africa/Addis_Ababa (UTC+03:00) 
                    Europe/Uzhgorod (UTC+03:00) 
                     Asia/Jerusalem (UTC+03:00) 
                        Asia/Riyadh (UTC+03:00) 
                        Asia/Kuwait (UTC+03:00) 
                       Europe/Kirov (UTC+03:00) 
                     Africa/Kampala (UTC+03:00) 
                       Europe/Minsk (UTC+03:00) 
                         Asia/Qatar (UTC+03:00) 
                        Europe/Kiev (UTC+03:00) 
                       Asia/Bahrain (UTC+03:00) 
                     Europe/Vilnius (UTC+03:00) 
                Indian/Antananarivo (UTC+03:00) 
                     Indian/Mayotte (UTC+03:00) 
                     Europe/Tallinn (UTC+03:00) 
                             Turkey (UTC+03:00) 
                        Africa/Juba (UTC+03:00) 
                       Asia/Nicosia (UTC+03:00) 
                     Asia/Famagusta (UTC+03:00) 
                               W-SU (UTC+03:00) 
                                EET (UTC+03:00) 
                        Asia/Hebron (UTC+03:00) 
                         Asia/Amman (UTC+03:00) 
                     Europe/Nicosia (UTC+03:00) 
                      Europe/Athens (UTC+03:00) 
                       Africa/Cairo (UTC+02:00) 
                     Africa/Mbabane (UTC+02:00) 
                    Europe/Brussels (UTC+02:00) 
                      Europe/Warsaw (UTC+02:00) 
                                CET (UTC+02:00) 
                  Europe/Luxembourg (UTC+02:00) 
                          Etc/GMT-2 (UTC+02:00) 
                              Libya (UTC+02:00) 
                      Africa/Kigali (UTC+02:00) 
                     Africa/Tripoli (UTC+02:00) 
                 Europe/Kaliningrad (UTC+02:00) 
                    Africa/Windhoek (UTC+02:00) 
                       Europe/Malta (UTC+02:00) 
                    Europe/Busingen (UTC+02:00) 
                      Europe/Skopje (UTC+02:00) 
                    Europe/Sarajevo (UTC+02:00) 
                        Europe/Rome (UTC+02:00) 
                      Europe/Zurich (UTC+02:00) 
                   Europe/Gibraltar (UTC+02:00) 
                  Africa/Lubumbashi (UTC+02:00) 
                       Europe/Vaduz (UTC+02:00) 
                   Europe/Ljubljana (UTC+02:00) 
                      Europe/Berlin (UTC+02:00) 
                   Europe/Stockholm (UTC+02:00) 
                    Europe/Budapest (UTC+02:00) 
                      Europe/Zagreb (UTC+02:00) 
                       Europe/Paris (UTC+02:00) 
                       Africa/Ceuta (UTC+02:00) 
                      Europe/Prague (UTC+02:00) 
                   Antarctica/Troll (UTC+02:00) 
                    Africa/Gaborone (UTC+02:00) 
                  Europe/Copenhagen (UTC+02:00) 
                      Europe/Vienna (UTC+02:00) 
                      Europe/Tirane (UTC+02:00) 
                                MET (UTC+02:00) 
                   Europe/Amsterdam (UTC+02:00) 
                      Africa/Maputo (UTC+02:00) 
                  Europe/San_Marino (UTC+02:00) 
                             Poland (UTC+02:00) 
                     Europe/Andorra (UTC+02:00) 
                        Europe/Oslo (UTC+02:00) 
                   Europe/Podgorica (UTC+02:00) 
                   Africa/Bujumbura (UTC+02:00) 
                 Atlantic/Jan_Mayen (UTC+02:00) 
                      Africa/Maseru (UTC+02:00) 
                      Europe/Madrid (UTC+02:00) 
                    Africa/Blantyre (UTC+02:00) 
                      Africa/Lusaka (UTC+02:00) 
                      Africa/Harare (UTC+02:00) 
                    Africa/Khartoum (UTC+02:00) 
                Africa/Johannesburg (UTC+02:00) 
                    Europe/Belgrade (UTC+02:00) 
                  Europe/Bratislava (UTC+02:00) 
                Arctic/Longyearbyen (UTC+02:00) 
                              Egypt (UTC+02:00) 
                     Europe/Vatican (UTC+02:00) 
                      Europe/Monaco (UTC+02:00) 
                      Europe/London (UTC+01:00) 
                          Etc/GMT-1 (UTC+01:00) 
                      Europe/Jersey (UTC+01:00) 
                    Europe/Guernsey (UTC+01:00) 
                 Europe/Isle_of_Man (UTC+01:00) 
                       Africa/Tunis (UTC+01:00) 
                      Africa/Malabo (UTC+01:00) 
                            GB-Eire (UTC+01:00) 
                       Africa/Lagos (UTC+01:00) 
                     Africa/Algiers (UTC+01:00) 
                                 GB (UTC+01:00) 
                           Portugal (UTC+01:00) 
                    Africa/Sao_Tome (UTC+01:00) 
                    Africa/Ndjamena (UTC+01:00) 
                    Atlantic/Faeroe (UTC+01:00) 
                               Eire (UTC+01:00) 
                     Atlantic/Faroe (UTC+01:00) 
                      Europe/Dublin (UTC+01:00) 
                  Africa/Libreville (UTC+01:00) 
                    Africa/El_Aaiun (UTC+01:00) 
                      Africa/Douala (UTC+01:00) 
                 Africa/Brazzaville (UTC+01:00) 
                  Africa/Porto-Novo (UTC+01:00) 
                   Atlantic/Madeira (UTC+01:00) 
                      Europe/Lisbon (UTC+01:00) 
                    Atlantic/Canary (UTC+01:00) 
                  Africa/Casablanca (UTC+01:00) 
                     Europe/Belfast (UTC+01:00) 
                      Africa/Luanda (UTC+01:00) 
                    Africa/Kinshasa (UTC+01:00) 
                      Africa/Bangui (UTC+01:00) 
                                WET (UTC+01:00) 
                      Africa/Niamey (UTC+01:00) 
                                GMT (UTC+00:00) 
                          Etc/GMT-0 (UTC+00:00) 
                 Atlantic/St_Helena (UTC+00:00) 
                          Etc/GMT+0 (UTC+00:00) 
                      Africa/Banjul (UTC+00:00) 
                            Etc/GMT (UTC+00:00) 
                    Africa/Freetown (UTC+00:00) 
                      Africa/Bamako (UTC+00:00) 
                     Africa/Conakry (UTC+00:00) 
                          Universal (UTC+00:00) 
                  Africa/Nouakchott (UTC+00:00) 
                                UTC (UTC+00:00) 
                      Etc/Universal (UTC+00:00) 
                    Atlantic/Azores (UTC+00:00) 
                     Africa/Abidjan (UTC+00:00) 
                       Africa/Accra (UTC+00:00) 
                            Etc/UCT (UTC+00:00) 
                               GMT0 (UTC+00:00) 
                               Zulu (UTC+00:00) 
                 Africa/Ouagadougou (UTC+00:00) 
                 Atlantic/Reykjavik (UTC+00:00) 
                           Etc/Zulu (UTC+00:00) 
                            Iceland (UTC+00:00) 
                        Africa/Lome (UTC+00:00) 
                          Greenwich (UTC+00:00) 
                           Etc/GMT0 (UTC+00:00) 
               America/Danmarkshavn (UTC+00:00) 
                       Africa/Dakar (UTC+00:00) 
               America/Scoresbysund (UTC+00:00) 
                      Africa/Bissau (UTC+00:00) 
                      Etc/Greenwich (UTC+00:00) 
                    Africa/Timbuktu (UTC+00:00) 
                                UCT (UTC+00:00) 
                    Africa/Monrovia (UTC+00:00) 
                            Etc/UTC (UTC+00:00) 

Total Zone IDs 599 

2.简化版本

2.1 这是由雷南创作的缩小版(评论如下)

DisplayZoneAndOffSet2.java

 package com.mkyong;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.AbstractMap.SimpleEntry;
import java.util.Map;

public class DisplayZoneAndOffSet2 {

    public static final boolean SORT_BY_REGION = false;

    public static void main(String[] args) {

        LocalDateTime localDateTime = LocalDateTime.now();

        long total = ZoneId.getAvailableZoneIds()
                .stream()
                .map(ZoneId::of)
                .map(zoneId -> new SimpleEntry<>(zoneId.toString(), localDateTime.atZone(zoneId)
                        .getOffset()
                        .getId()
                        .replaceAll("Z", "+00:00")))
                .sorted(SORT_BY_REGION
                        ? Map.Entry.comparingByKey()
                        : Map.Entry.<String, String>comparingByValue().reversed())
                .peek(e -> System.out.printf(String.format("%35s (UTC%s) %n", e.getKey(), e.getValue())))
                .count();

        System.out.println("\nTotal Zone IDs " + total);

    }
} 

它在 Java 8 中可以工作,但是由于这个count()问题,在 Java 9 和更高版本中‘peek()’将无法打印

2.2 我修改了一点,返回一个新的排序图。用 Java 8 和 Java 12 测试。

DisplayZoneAndOffSet3.java

 package com.mkyong;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.AbstractMap.SimpleEntry;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class DisplayZoneAndOffSet3 {

    public static final boolean SORT_BY_REGION = false;

    public static void main(String[] args) {

        LocalDateTime localDateTime = LocalDateTime.now();

        Map<String, String> result = ZoneId.getAvailableZoneIds()
                .stream()
                .map(ZoneId::of)
                .map(zoneId -> new SimpleEntry<>(zoneId.toString(), localDateTime.atZone(zoneId)
                        .getOffset()
                        .getId()
                        .replaceAll("Z", "+00:00")))
                .sorted(SORT_BY_REGION
                        ? Map.Entry.comparingByKey()
                        : Map.Entry.<String, String>comparingByValue().reversed())
                .collect(Collectors.toMap(
                        SimpleEntry::getKey,
                        SimpleEntry::getValue,
                        (oldValue, newValue) -> oldValue,
                        LinkedHashMap::new));

        result.forEach((k, v) -> System.out.printf(String.format("%35s (UTC%s) %n", k, v)));

        System.out.println("\nTotal Zone IDs " + result.size());

    }
} 

参考

Java DOM 解析器 XML 和 XSLT 示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-dom-parser-xml-and-xslt-examples/

使用 XSLT (可扩展样式表语言转换),我们可以将 XML 文档转换成其他格式,比如 HTML。

目录

PS 用 Java 11 测试过

1。DOM 解析器和转换器

我们可以使用TransformerFactory来应用XSLT文件,将 XML 文件转换成另一种格式。

 TransformerFactory transformerFactory = TransformerFactory.newInstance();

  // add XSLT in Transformer
  Transformer transformer = transformerFactory.newTransformer(
          new StreamSource(new File("format.xslt")));

  transformer.transform(new DOMSource(doc), new StreamResult(output)); 

2。DOM 示例:XML + XSLT = HTML 格式

下面是一个 Java DOM 解析器示例,用于解析 XML 文件,应用 XSLT 文件并将 XML 文件转换为 HTML 文件。

2.1 一个 XML 文件。

staff-simple.xml

 <?xml version="1.0" encoding="utf-8"?>
<company>
    <staff id="1001">
        <name>mkyong</name>
        <role>support</role>
    </staff>
    <staff id="1002">
        <name>yflow</name>
        <role>admin</role>
    </staff>
</company> 

2.2 应用下面的 XSLT 文件会将 XML 文件转换成 HTML 格式。

staff-xml-html.xslt

 <?xml version="1.0" encoding="UTF-8"?>
<html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <body style="font-size:12pt;background-color:#EEEEEE">
        <h1 style="font-size:20pt;color:#FF0000">Hello World DOM + XML + XSLT</h1>
        <xsl:for-each select="company/staff">
            <ul>
                <li>
                    <xsl:value-of select="@id"/> -
                    <xsl:value-of select="name"/> -
                    <xsl:value-of select="role"/>
                </li>
            </ul>
        </xsl:for-each>
    </body>
</html> 

2.3 输出,一个 HTML 文件。

 <html>
  <body style="font-size:12pt;background-color:#EEEEEE">
      <h1 style="font-size:20pt;color:#FF0000">Hello World DOM + XML + XSLT</h1>
      <ul>
          <li>1001 -
                  mkyong -
                  support</li>
      </ul>
      <ul>
          <li>1002 -
                  yflow -
                  admin</li>
      </ul>
  </body>
</html> 

2.4 下面是做 XSLT 转换的 Java DOM 解析器。

XsltXmlToHtmlDomParser.java

 package com.mkyong.xml.dom;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.*;

// XML -> XSLT -> Other formats
public class XsltXmlToHtmlDomParser{

    private static final String XML_FILENAME
                          = "src/main/resources/staff-simple.xml";
    private static final String XSLT_FILENAME
                          = "src/main/resources/xslt/staff-xml-html.xslt";

    public static void main(String[] args) {

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

        try (InputStream is = new FileInputStream(XML_FILENAME)) {

            DocumentBuilder db = dbf.newDocumentBuilder();

            Document doc = db.parse(is);

            // transform xml to html via a xslt file
            try (FileOutputStream output =
                         new FileOutputStream("c:\\test\\staff.html")) {
                transform(doc, output);
            }

        } catch (IOException | ParserConfigurationException |
            SAXException | TransformerException e) {
            e.printStackTrace();
        }

    }

    private static void transform(Document doc, OutputStream output)
            throws TransformerException {

        TransformerFactory transformerFactory = TransformerFactory.newInstance();

        // add XSLT in Transformer
        Transformer transformer = transformerFactory.newTransformer(
                new StreamSource(new File(XSLT_FILENAME)));

        transformer.transform(new DOMSource(doc), new StreamResult(output));

    }

} 

输出-c:\\test\\staff.html

xml to html file

3。下载源代码

$ git 克隆https://github.com/mkyong/core-java

$ cd java-xml

$ CD src/main/Java/com/mkyong/XML/DOM/XSLT/

4。参考文献

Java 斐波那契示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-fibonacci-examples/

斐波那契数–前两个数字之后的每一个数字都是前两个数字的总和。

几个寻找斐波那契数列的 Java 例子。

1.Java 8 流

1.1 在 Java 8 中,我们可以像这样使用Stream.iterate来生成斐波那契数:

 Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1], t[0] + t[1]})
		.limit(10)
		.forEach(x -> System.out.println("{" + x[0] + "," + x[1] + "}")); 

输出

 {0,1}
{1,1}
{1,2}
{2,3}
{3,5}
{5,8}
{8,13}
{13,21}
{21,34}
{34,55} 

P.S 回顾一下上面的输出,第一个值就是我们想要的。

1.2 最终版本。

 Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1], t[0] + t[1]})
		.limit(10)
		.map(t -> t[0])
		.forEach(x -> System.out.println(x)); 

输出

 0
1
1
2
3
5
8
13
21
34 

1.3 对所有斐波纳契数列求和

 int sum = Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1], t[0] + t[1]})
		.limit(10)
		.map(t -> t[0])
		.mapToInt(Integer::intValue)
		.sum();

    System.out.println("Total : " + sum); 

输出

 Total : 88 

1.4 用逗号连接。

 String collect = Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1], t[0] + t[1]})
                .limit(10)
                .map(t -> t[0])
                .map(String::valueOf) // convert to string
                .collect(Collectors.joining(", "));

        System.out.println("Result : " + collect); 

输出

 Result : 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 

1.5 创建斐波那契数列的函数。

 package com.mkyong.concurrency;

import java.util.List;
import java.util.stream.Stream;

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

public class Fibonacci {

    public static List<Integer> getFibonacci(int series) {
        return Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1], t[0] + t[1]})
                .limit(series)
                .map(n -> n[0])
                .collect(toList());
    }

    public static void main(String[] args) {

        List<Integer> fibonacci = getFibonacci(10);
        fibonacci.forEach(x -> System.out.println(x));

    }

} 

输出

 0
1
1
2
3
5
8
13
21
34 

1.6 类型intlong不足以存储更大的斐波那契数。下面是寻找第一百万个斐波那契数列的BigInteger例子。

 package com.mkyong.concurrency;

import java.math.BigInteger;
import java.util.stream.Stream;

public class Fibonacci {

    public static BigInteger getFibonacci(int series) {
        return Stream.iterate(new BigInteger[]{
                BigInteger.ZERO, BigInteger.ONE}, t -> new BigInteger[]{t[1], t[0].add(t[1])})
                .limit(series)
                .map(n -> n[1]) // find, we need n[1]
                .reduce((a, b) -> b).orElse(BigInteger.ZERO);

    }

    public static void main(String[] args) {
        System.out.println(Fibonacci.getFibonacci(1_000_000));
    }

} 

输出

 1953282128707757731632014947596256332443... // 208,988 digits!!!, too long to display here 

2.递归循环

2.1 Java 递归循环例子,创建一个斐波那契数列。只适合演示,这个递归循环很慢。

Fibonacci.java

 package com.mkyong.concurrency;

public class Fibonacci {

    public static int fib(int n) {
        if (n <= 1) return n;
        else return fib(n - 1) + fib(n - 2);
    }

    public static void main(String[] args) {

        for (int i = 0; i < 10; i++) {
            System.out.println(fib(i));
        }

    }

} 

输出

 0
1
1
2
3
5
8
13
21
34 

2.2 工作原理?

 fib(n) = fib(n - 1) + fib(n - 2);

fib(5) = fib(4) + fib(3);
fib(4) = fib(3) + fib(2);
fib(3) = fib(2) + fib(1);
fib(2) = fib(1) + fib(0);
fib(1) = 1
fib(0) = 1 

3.正常循环

3.1 Java 普通循环寻找斐波那契数列,简单易行。

Fibonacci.java

 package com.mkyong.concurrency;

import java.math.BigInteger;

public class Fibonacci {

    public static int fib(int n) {
        if (n <= 1) return n;

        int previous = 0, next = 1, sum;

        for (int i = 2; i <= n; i++) {
            sum = previous;
            previous = next;
            next = sum + previous;
        }

        return next;
    }

    public static BigInteger fib2(int n) {
        if (n <= 1) return BigInteger.valueOf(n);

        BigInteger previous = BigInteger.ZERO, next = BigInteger.ONE, sum;

        for (int i = 2; i <= n; i++) {
            sum = previous;
            previous = next;
            next = sum.add(previous);
        }

        return next;
    }

    public static void main(String[] args) {

        for (int i = 0; i < 10; i++) {
            System.out.println(fib(i));
        }

        System.out.println("---");

        for (int i = 0; i < 10; i++) {
            System.out.println(fib2(i));
        }

        System.out.println("---");

        System.out.println(fib(100)); //overflow
        System.out.println(fib2(100));
    }

} 

输出

 0
1
1
2
3
5
8
13
21
34
---
0
1
1
2
3
5
8
13
21
34
---
-980107325
354224848179261915075 

Note
Please use BigInteger to store the Fibonacci numbers to avoid an overflow issue.

参考

  1. 斐波那契数

Java 文件.查找示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-files-find-examples/

从 Java 8 开始就有了Files.find API。它从文件树中快速搜索或查找文件。

主题

  1. Files.find()方法签名
  2. 通过文件名查找文件
  3. 根据文件大小查找文件
  4. 根据最后修改时间查找文件

在过去,我们总是使用容易出错的递归循环来遍历文件树。这个 Java 8 Files.find可以帮你节省很多时间。

1。Files.find()签名

查看Files.find()签名。

Files.java

 public static Stream<Path> find(Path start,
                                int maxDepth,
                                BiPredicate<Path, BasicFileAttributes> matcher,
                                FileVisitOption... options)
        throws IOException 
  • path,起始文件或文件夹。
  • maxDepth定义了要搜索的最大目录级别数。如果我们放置1,这意味着只搜索顶层或根文件夹,忽略它的所有子文件夹;如果我们想搜索所有的文件夹级别,请输入Integer.MAX_VALUE
  • BiPredicate<Path, BasicFileAttributes>用于条件检查或过滤。
  • FileVisitOption告诉我们是否要跟随符号链接,默认是 no。我们可以让FileVisitOption.FOLLOW_LINKS跟随符号链接。

2。通过文件名

查找文件

这个例子使用Files.find()来查找与文件名google.png匹配的文件,从文件夹C:\\test开始,包括它的所有子文件夹。

FileFindExample1.java

 package com.mkyong.io.api;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class FileFindExample1 {

    public static void main(String[] args) throws IOException {

        Path path = Paths.get("C:\\test");
        List<Path> result = findByFileName(path, "google.png");
        result.forEach(x -> System.out.println(x));

    }

    public static List<Path> findByFileName(Path path, String fileName)
            throws IOException {

        List<Path> result;
        try (Stream<Path> pathStream = Files.find(path,
                Integer.MAX_VALUE,
                (p, basicFileAttributes) ->
                        p.getFileName().toString().equalsIgnoreCase(fileName))
        ) {
            result = pathStream.collect(Collectors.toList());
        }
        return result;

    }

} 

我们还可以使用FilesAPI 来进一步检查路径。

FileFindExample1.java

 try (Stream<Path> pathStream = Files.find(path,
         Integer.MAX_VALUE,
         (p, basicFileAttributes) ->{
             // if directory or no-read permission, ignore
             if(Files.isDirectory(p) || !Files.isReadable(p)){
                 return false;
             }
             return p.getFileName().toString().equalsIgnoreCase(fileName);
         })
 ) 

3。按文件大小查找文件

这个例子使用Files.find()来查找文件大小大于或等于 100MB 的文件。

FileFindExample2.java

 package com.mkyong.io.api;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class FileFindExample2 {

    public static void main(String[] args) throws IOException {

        Path path = Paths.get("C:\\Users\\mkyong\\Downloads");

        long fileSize = 1024 * 1024 * 100; // 100M

        List<Path> result = findByFileSize(path, fileSize);
        for (Path p : result) {
            System.out.println(String.format("%-40s [fileSize]: %,d", p, Files.size(p)));
        }

    }

    public static List<Path> findByFileSize(Path path, long fileSize)
            throws IOException {

        List<Path> result;
        try (Stream<Path> pathStream = Files.find(path,
                Integer.MAX_VALUE,
                (p, basicFileAttributes) -> {
                    try {
                        if (Files.isDirectory(p)) {   // ignore directory
                            return false;
                        }
                        return Files.size(p) >= fileSize;
                    } catch (IOException e) {
                        System.err.println("Unable to get the file size of path : " + path);
                    }
                    return false;
                }

        )) {
            result = pathStream.collect(Collectors.toList());
        }
        return result;

    }

} 

输出样本。

Terminal

 C:\Users\mkyong\Downloads\hello.mp4 [fileSize]: 4,796,543,886
C:\Users\mkyong\Downloads\java.mp4.bk [fileSize]: 5,502,785,778
C:\Users\mkyong\Downloads\ubuntu-20.04.1-desktop-amd64.iso [fileSize]: 2,785,017,856

#... 

4。按最后修改时间

查找文件

这个例子使用File.find()来查找包含上次修改时间等于或晚于昨天的文件。

FileFindExample3.java

 package com.mkyong.io.api;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class FileFindExample3 {

    private static DateTimeFormatter DATE_FORMATTER
            = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss");

    public static void main(String[] args) throws IOException {

        // find files, LastModifiedTime from yesterday and above
        List<Path> result = findByLastModifiedTime(
                Paths.get("C:\\test"),
                Instant.now().minus(1, ChronoUnit.DAYS));

        for (Path p : result) {

            // formatting...
            BasicFileAttributes attrs = Files.readAttributes(p, BasicFileAttributes.class);
            FileTime time = attrs.lastModifiedTime();
            LocalDateTime localDateTime = time.toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDateTime();

            System.out.println(String.format("%-40s [%s]", p, localDateTime.format(DATE_FORMATTER)));
        }

    }

    public static List<Path> findByLastModifiedTime(Path path, Instant instant)
            throws IOException {

        List<Path> result;
        try (Stream<Path> pathStream = Files.find(path,
                Integer.MAX_VALUE,
                (p, basicFileAttributes) -> {

                    if(Files.isDirectory(p) || !Files.isReadable(p)){
                        return false;
                    }

                    FileTime fileTime = basicFileAttributes.lastModifiedTime();
                    // negative if less, positive if greater
                    // 1 means fileTime equals or after the provided instant argument
                    // -1 means fileTime before the provided instant argument
                    int i = fileTime.toInstant().compareTo(instant);
                    return i > 0;
                }

        )) {
            result = pathStream.collect(Collectors.toList());
        }
        return result;

    }

} 

输出样本并假设今天是02/12/2020

Terminal

 C:\test\a.txt                          [02/12/2020 13:01:20]
C:\test\b.txt                          [01/12/2020 12:11:21]

#... 

下载源代码

$ git 克隆https://github.com/mkyong/core-java

$ cd java-io

参考文献

Java Files.walk 示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-files-walk-examples/

从 Java 8 开始就有了Files.walkAPI;它有助于在给定的起始路径遍历文件树。

主题

  1. Files.walk()方法签名
  2. 列出所有文件
  3. 列出所有文件夹或目录
  4. 通过文件扩展名查找文件
  5. 通过文件名查找文件
  6. 根据文件大小查找文件
  7. 更新所有文件最后修改日期

1。Files.walk()方法签名

查看 Files.walk 方法签名。

Files.java

 public static Stream<Path> walk(Path start, FileVisitOption... options)
        throws IOException {

        return walk(start, Integer.MAX_VALUE, options);
    }

    public static Stream<Path> walk(Path start,
                                    int maxDepth,
                                    FileVisitOption... options)
        throws IOException
    { 
  • path,起始文件或文件夹。
  • maxDepth,要搜索的最大目录级别数,如果省略,默认为Integer.MAX_VALUE,表示要搜索的2,147,483,647个目录级别。简而言之,默认情况下,它将搜索目录的所有级别。如果我们只想从顶层或根目录进行搜索,就使用1
  • FileVisitOption告诉我们是否要跟随符号链接,默认是 no。我们可以让FileVisitOption.FOLLOW_LINKS跟随符号链接。

2。列出所有文件

这个例子使用Files.walk列出一个目录中的所有文件,包括所有级别的子目录(默认)。

FilesWalkExample1.java

 package com.mkyong.io.api;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class FilesWalkExample1 {

    public static void main(String[] args) throws IOException {

        Path path = Paths.get("C:\\test\\");
        List<Path> paths = listFiles(path);
        paths.forEach(x -> System.out.println(x));

    }

    // list all files from this path
    public static List<Path> listFiles(Path path) throws IOException {

        List<Path> result;
        try (Stream<Path> walk = Files.walk(path)) {
            result = walk.filter(Files::isRegularFile)
                    .collect(Collectors.toList());
        }
        return result;

    }

} 

输出

Terminal

 C:\test\bk\logo-new.png
C:\test\bk\New Text Document.txt
C:\test\bk\readme.encrypted.txt
C:\test\bk\readme.txt
C:\test\data\ftp\google.png
C:\test\example.json
C:\test\google-decode.png
C:\test\google.png 

如果我们只想列出根目录中的文件,请输入maxDepth = 1

FilesWalkExample1.java

 try (Stream<Path> walk = Files.walk(path, 1)) {
        result = walk.filter(Files::isRegularFile)
                .collect(Collectors.toList());
    } 

输出

Terminal

 C:\test\example.json
C:\test\google-decode.png
C:\test\google.png 

3。列出所有文件夹或目录

 // list all directories from this path
    public static List<Path> listDirectories(Path path) throws IOException {

        List<Path> result;
        try (Stream<Path> walk = Files.walk(path)) {
            result = walk.filter(Files::isDirectory)
                    .collect(Collectors.toList());
        }
        return result;

    } 

输出

Terminal

 C:\test
C:\test\bk
C:\test\data
C:\test\data\ftp
C:\test\test1
C:\test\test1\test2 

4。通过文件扩展名

查找文件

这个例子使用Files.walk从一个路径中查找所有文本文件.txt

FilesWalkExample4.java

 package com.mkyong.io.api;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class FilesWalkExample4 {

    public static void main(String[] args) throws IOException {

        Path path = Paths.get("C:\\test\\");
        List<Path> paths = findByFileExtension(path, ".txt");
        paths.forEach(x -> System.out.println(x));

    }

    public static List<Path> findByFileExtension(Path path, String fileExtension)
            throws IOException {

        if (!Files.isDirectory(path)) {
            throw new IllegalArgumentException("Path must be a directory!");
        }

        List<Path> result;
        try (Stream<Path> walk = Files.walk(path)) {
            result = walk
                    .filter(Files::isRegularFile)   // is a file
                    .filter(p -> p.getFileName().toString().endsWith(fileExtension))
                    .collect(Collectors.toList());
        }
        return result;

    }

} 

输出

Terminal

 C:\test\bk\New Text Document.txt
C:\test\bk\readme.encrypted.txt
C:\test\bk\readme.txt 

5。通过文件名

查找文件

 public static List<Path> findByFileName(Path path, String fileName)
      throws IOException {

      if (!Files.isDirectory(path)) {
          throw new IllegalArgumentException("Path must be a directory!");
      }

      List<Path> result;
      // walk file tree, no more recursive loop
      try (Stream<Path> walk = Files.walk(path)) {
          result = walk
                  .filter(Files::isReadable)      // read permission
                  .filter(Files::isRegularFile)   // is a file
                  .filter(p -> p.getFileName().toString().equalsIgnoreCase(fileName))
                  .collect(Collectors.toList());
      }
      return result;

  } 

6。按文件大小查找文件

查找文件大小大于或等于 10MB 的所有文件。

FilesWalkExample6.java

 package com.mkyong.io.api;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

// Files.walk example
public class FilesWalkExample6 {

    public static void main(String[] args) throws IOException {

        Path path = Paths.get("C:\\test\\");

        long fileSizeInBytes = 1024 * 1024 * 10; // 10MB

        List<Path> paths = findByFileSize(path, fileSizeInBytes);
        paths.forEach(x -> System.out.println(x));

    }

    // fileSize in bytes
    public static List<Path> findByFileSize(Path path, long fileSize)
        throws IOException {

        if (!Files.isDirectory(path)) {
            throw new IllegalArgumentException("Path must be a directory!");
        }

        List<Path> result;
        // walk file tree, no more recursive loop
        try (Stream<Path> walk = Files.walk(path)) {
            result = walk
                    .filter(Files::isReadable)              // read permission
                    .filter(p -> !Files.isDirectory(p))     // is a file
                    .filter(p -> checkFileSize(p, fileSize))
                    .collect(Collectors.toList());
        }
        return result;

    }

    private static boolean checkFileSize(Path path, long fileSize) {
        boolean result = false;
        try {
            if (Files.size(path) >= fileSize) {
                result = true;
            }
        } catch (IOException e) {
            System.err.println("Unable to get the file size of this file: " + path);
        }
        return result;
    }

} 

7。更新所有文件最后修改日期

此示例将所有文件的最后修改日期从路径更新为昨天。

FilesWalkExample7.java

 package com.mkyong.io.api;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileTime;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.stream.Stream;

public class FilesWalkExample7 {

    public static void main(String[] args) throws IOException {

        Path path = Paths.get("C:\\test\\");

        Instant yesterday = Instant.now().minus(1, ChronoUnit.DAYS);
        setAllFilesModifiedDate(path, yesterday);

    }

    // set all files' last modified time to this instant
    public static void setAllFilesModifiedDate(Path path, Instant instant)
        throws IOException {

        try (Stream<Path> walk = Files.walk(path)) {
            walk
                    .filter(Files::isReadable)      // read permission
                    .filter(Files::isRegularFile)   // file only
                    .forEach(p -> {
                        try {
                            // set last modified time
                            Files.setLastModifiedTime(p, FileTime.from(instant));
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    });
        }
    }

} 

下载源代码

$ git 克隆https://github.com/mkyong/core-java

$ cd java-io

参考文献

Java——生成一个范围内的随机整数

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-generate-random-integers-in-a-range/

java-random-integer-in-range

在本文中,我们将向您展示在一个范围内生成随机整数的三种方法。

  1. java.util.Random.nextInt
  2. 数学.随机
  3. java.util.Random.ints (Java 8)

1.java.util.Random

Random().nextInt(int bound)生成一个从 0(含)到界(不含)的随机整数。

1.1 代码片段。对于getRandomNumberInRange(5, 10),这将生成一个介于 5(含)和 10(含)之间的随机整数。

 private static int getRandomNumberInRange(int min, int max) {

		if (min >= max) {
			throw new IllegalArgumentException("max must be greater than min");
		}

		Random r = new Random();
		return r.nextInt((max - min) + 1) + min;
	} 

1.2 什么是(最大–最小)+ 1) +最小?

上述公式将生成一个介于最小值(含)和最大值(含)之间的随机整数。

 //Random().nextInt(int bound) = Random integer from 0 (inclusive) to bound (exclusive)

	//1\. nextInt(range) = nextInt(max - min)
	new Random().nextInt(5);  // [0...4] [min = 0, max = 4]
	new Random().nextInt(6);  // [0...5]
	new Random().nextInt(7);  // [0...6]
	new Random().nextInt(8);  // [0...7]
	new Random().nextInt(9);  // [0...8]
	new Random().nextInt(10); // [0...9]			
	new Random().nextInt(11); // [0...10]

	//2\. To include the last value (max value) = (range + 1)
	new Random().nextInt(5 + 1)  // [0...5] [min = 0, max = 5]
	new Random().nextInt(6 + 1)  // [0...6]
	new Random().nextInt(7 + 1)  // [0...7]
	new Random().nextInt(8 + 1)  // [0...8]
	new Random().nextInt(9 + 1)  // [0...9]
	new Random().nextInt(10 + 1) // [0...10]			
	new Random().nextInt(11 + 1) // [0...11]

	//3\. To define a start value (min value) in a range,
	//   For example, the range should start from 10 = (range + 1) + min
	new Random().nextInt(5 + 1)  + 10 // [0...5]  + 10 = [10...15]
	new Random().nextInt(6 + 1)  + 10 // [0...6]  + 10 = [10...16]
	new Random().nextInt(7 + 1)  + 10 // [0...7]  + 10 = [10...17]
	new Random().nextInt(8 + 1)  + 10 // [0...8]  + 10 = [10...18]
	new Random().nextInt(9 + 1)  + 10 // [0...9]  + 10 = [10...19]
	new Random().nextInt(10 + 1) + 10 // [0...10] + 10 = [10...20]
	new Random().nextInt(11 + 1) + 10 // [0...11] + 10 = [10...21]

	// Range = (max - min)
	// So, the final formula is ((max - min) + 1) + min

	//4\. Test [10...30]
	// min = 10 , max = 30, range = (max - min)
	new Random().nextInt((max - min) + 1) + min
	new Random().nextInt((30 - 10) + 1) + 10
	new Random().nextInt((20) + 1) + 10
	new Random().nextInt(21) + 10    //[0...20] + 10 = [10...30]

	//5\. Test [15...99]
	// min = 15 , max = 99, range = (max - min)
	new Random().nextInt((max - min) + 1) + min
	new Random().nextInt((99 - 15) + 1) + 15
	new Random().nextInt((84) + 1) + 15
	new Random().nextInt(85) + 15    //[0...84] + 15 = [15...99]

	//Done, understand? 

1.3 产生 10 个范围在 5(含)和 10(含)之间的随机整数的完整示例。

TestRandom.java

 package com.mkyong.example.test;

import java.util.Random;

public class TestRandom {

	public static void main(String[] args) {

		for (int i = 0; i < 10; i++) {
			System.out.println(getRandomNumberInRange(5, 10));
		}

	}

	private static int getRandomNumberInRange(int min, int max) {

		if (min >= max) {
			throw new IllegalArgumentException("max must be greater than min");
		}

		Random r = new Random();
		return r.nextInt((max - min) + 1) + min;
	}

} 

输出。

 7
6
10
8
9
5
7
10
8
5 

2.数学.随机

这个Math.random()给出一个从 0.0(含)到 1.0(不含)的随机双精度。

2.1 代码片段。参考 1.2,或多或少是同一个公式。

 (int)(Math.random() * ((max - min) + 1)) + min 

2.2 生成 10 个随机整数的完整示例,范围在 16(含)和 20(含)之间。

TestRandom.java

 package com.mkyong.example.test;

public class TestRandom {

	public static void main(String[] args) {

		for (int i = 0; i < 10; i++) {
			System.out.println(getRandomNumberInRange(16, 20));
		}

	}

	private static int getRandomNumberInRange(int min, int max) {

		if (min >= max) {
			throw new IllegalArgumentException("max must be greater than min");
		}

		return (int)(Math.random() * ((max - min) + 1)) + min;
	}

} 

输出。

 17
16
20
19
20
20
20
17
20
16 

Note
The Random.nextInt(n) is more efficient than Math.random() * n, read this Oracle forum post.

3.Java 8 Random.ints

在 Java 8 中,在java.util.Random中增加了新的方法

 public IntStream ints(int randomNumberOrigin, int randomNumberBound)
	public IntStream ints(long streamSize, int randomNumberOrigin, int randomNumberBound) 

这个Random.ints(int origin, int bound)Random.ints(int min, int max)生成一个从原点(含)到界(不含)的随机整数。

3.1 代码片段。

 private static int getRandomNumberInRange(int min, int max) {

		Random r = new Random();
		return r.ints(min, (max + 1)).findFirst().getAsInt();

	} 

3.2 产生 10 个范围在 33(含)和 38(含)之间的随机整数的完整示例。

TestRandom.java

 package com.mkyong.form.test;

import java.util.Random;

public class TestRandom {

	public static void main(String[] args) {

		for (int i = 0; i < 10; i++) {
			System.out.println(getRandomNumberInRange(33, 38));
		}

	}

	private static int getRandomNumberInRange(int min, int max) {

		Random r = new Random();
		return r.ints(min, (max + 1)).limit(1).findFirst().getAsInt();

	}

} 

输出。

 34
35
37
33
38
37
34
35
36
37 

3.3 额外,供自我参考。

生成介于 33(含)和 38(不含)之间的随机整数,流大小为 10。并打印出带有forEach的项目。

 //Java 8 only
	new Random().ints(10, 33, 38).forEach(System.out::println); 

输出。

 34
37
37
34
34
35
36
33
37
34 

参考

  1. java.util.Random JavaDoc
  2. java.lang.Math JavaDoc
  3. 甲骨文论坛:随机数生成
  4. 在 JavaScript 中生成加权随机数

Java——获取正在运行的 JAR 文件的名称或路径

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-get-the-name-or-path-of-a-running-jar-file/

在 Java 中,我们可以使用下面的代码片段来获取正在运行的 JAR 文件的路径。

 // static
  String jarPath = ClassName.class
          .getProtectionDomain()
          .getCodeSource()
          .getLocation()
          .toURI()
          .getPath();

  // non-static
  String jarPath = getClass()
          .getProtectionDomain()
          .getCodeSource()
          .getLocation()
          .toURI()
          .getPath(); 

样本输出。

Terminal

 /home/mkyong/projects/core-java/java-io/target/java-io.jar 

1.获取运行 JAR 的路径

1.1 创建一个可执行 JAR 文件。

pom.xml

 <!-- Make this jar executable -->
  <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-jar-plugin</artifactId>
      <version>3.2.0</version>
      <configuration>
          <archive>
              <manifest>
                  <addClasspath>true</addClasspath>
                  <mainClass>com.mkyong.io.howto.resources.TestApp</mainClass>
              </manifest>
          </archive>
      </configuration>
  </plugin> 

1.2 运行下面的代码,以获取正在运行的 JAR 文件的名称或路径。

TestApp.java

 package com.mkyong.io.howto.resources;

import java.net.URISyntaxException;

public class TestApp {

    public static void main(String[] args) {

        TestApp obj = new TestApp();

        try {

            // Get path of the JAR file
            String jarPath = TestApp.class
                    .getProtectionDomain()
                    .getCodeSource()
                    .getLocation()
                    .toURI()
                    .getPath();
            System.out.println("JAR Path : " + jarPath);

            // Get name of the JAR file
            String jarName = jarPath.substring(jarPath.lastIndexOf("/") + 1);
            System.out.printf("JAR Name: " + jarName);

        } catch (URISyntaxException e) {
            e.printStackTrace();
        }

    }

} 

输出

Terminal

 $ mvn clean package

$ java -jar target/java-io.jar

JAR Path : /home/mkyong/projects/core-java/java-io/target/java-io.jar
JAR Name: java-io.jar 

2.toURI()?

如果文件名或文件路径包含特殊字符,例如%.getLocation.getPath()将对特殊字符进行编码。

 try {

      // return raw, no encode
      String jarPath = TestApp.class
              .getProtectionDomain()
              .getCodeSource()
              .getLocation()
              .toURI()
              .getPath();
      System.out.println("JAR Path : " + jarPath);

      // url encoded
      String jarPath2 = TestApp.class
              .getProtectionDomain()
              .getCodeSource()
              .getLocation() //.toURI
              .getPath();
      System.out.println("JAR Path 2 : " + jarPath2);

  } catch (URISyntaxException e) {
      e.printStackTrace();
  } 

输出

Terminal

 $ java -jar java-io%test.jar

JAR Path : /home/mkyong/projects/core-java/java-io/target/java-io%test.jar

JAR Path 2 : /home/mkyong/projects/core-java/java-io/target/java-io%25test.jar 

下载源代码

$ git 克隆https://github.com/mkyong/core-java

$ cd java-io

参考

Java——如何给当前日期添加天数

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-how-to-add-days-to-current-date/

本文向您展示了如何使用传统的java.util.Calendar和新的 Java 8 日期和时间 API 向当前日期添加天数。

1.Calendar.add

向当前日期添加 1 年 1 个月 1 天 1 小时 1 分 1 秒的示例。

DateExample.java

 package com.mkyong.time;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class DateExample {

    private static final DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

    public static void main(String[] args) {

        Date currentDate = new Date();
        System.out.println(dateFormat.format(currentDate));

        // convert date to calendar
        Calendar c = Calendar.getInstance();
        c.setTime(currentDate);

        // manipulate date
        c.add(Calendar.YEAR, 1);
        c.add(Calendar.MONTH, 1);
        c.add(Calendar.DATE, 1); //same with c.add(Calendar.DAY_OF_MONTH, 1);
        c.add(Calendar.HOUR, 1);
        c.add(Calendar.MINUTE, 1);
        c.add(Calendar.SECOND, 1);

        // convert calendar to date
        Date currentDatePlusOne = c.getTime();

        System.out.println(dateFormat.format(currentDatePlusOne));

    }

} 

输出

 2016/11/10 17:11:48
2017/12/11 18:12:49 

2.Java 8 加减

在 Java 8 中,您可以使用加号和减号方法来操作 LocalDate、LocalDateTime 和 ZoneDateTime,请参见以下示例

LocalDateTimeExample.java

 package com.mkyong.time;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;

public class LocalDateTimeExample {

    private static final String DATE_FORMAT = "yyyy/MM/dd HH:mm:ss";
    private static final DateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
    private static final DateTimeFormatter dateFormat8 = DateTimeFormatter.ofPattern(DATE_FORMAT);

    public static void main(String[] args) {

		// Get current date
        Date currentDate = new Date();
        System.out.println("date : " + dateFormat.format(currentDate));

        // convert date to localdatetime
        LocalDateTime localDateTime = currentDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        System.out.println("localDateTime : " + dateFormat8.format(localDateTime));

        // plus one
        localDateTime = localDateTime.plusYears(1).plusMonths(1).plusDays(1);
        localDateTime = localDateTime.plusHours(1).plusMinutes(2).minusMinutes(1).plusSeconds(1);

        // convert LocalDateTime to date
        Date currentDatePlusOneDay = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());

        System.out.println("\nOutput : " + dateFormat.format(currentDatePlusOneDay));

    }

} 

输出

 date : 2016/11/10 17:40:11
localDateTime : 2016/11/10 17:40:11

Output : 2017/12/11 18:41:12 

参考

  1. 日历 JavaDoc
  2. Java–如何获取当前日期时间–date()和 calendar()
  3. Java 8–将日期转换为本地日期和本地日期时间

Java——如何改变字符串中的日期格式

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-how-to-change-date-format-in-a-string/

如果 Java 8,DateTimeFormatter,否则SimpleDateFormat改变字符串中的日期格式。

1. DateTimeFormatter (Java 8)

将字符串转换为LocalDateTime并用DateTimeFormatter改变日期格式

DateFormatExample1.java

 package com.mkyong;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class DateFormatExample1 {

	// date format 1
    private static final DateTimeFormatter dateFormatter 
		= DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S");

	// date format 2
    private static final DateTimeFormatter dateFormatterNew 
		= DateTimeFormatter.ofPattern("EEEE, MMM d, yyyy HH:mm:ss a");

    public static void main(String[] args) {

        String date = "2019-05-23 00:00:00.0";

		// string to LocalDateTime
        LocalDateTime ldateTime = LocalDateTime.parse(date, dateFormatter);

        System.out.println(dateFormatter.format(ldateTime));

        // change date format
        System.out.println(dateFormatterNew.format(ldateTime));

    }

} 

输出

 2019-05-23 00:00:00.0

Thursday, May 23, 2019 00:00:00 AM 

Note
More Java 8 String to LocalDateTime examples

2.简单日期格式

将字符串转换为Date并用SimpleDateFormat改变日期格式

SimpleDateFormatExample.java

 package com.mkyong;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class SimpleDateFormatExample {

    private static final SimpleDateFormat sdf = 
			new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");

    private static final SimpleDateFormat sdfNew = 
			new SimpleDateFormat("EEEE, MMM d, yyyy HH:mm:ss a");

    public static void main(String[] args) {

        String dateString = "2019-05-23 00:00:00.0";

        try {

			// string to date
            Date date = sdf.parse(dateString);

            System.out.println(sdf.format(date));

            System.out.println(sdfNew.format(date));

        } catch (ParseException e) {
            e.printStackTrace();
        }

    }

} 

输出

 2019-05-23 00:00:00.0

Thursday, May 23, 2019 00:00:00 AM 

Note
More Java String to Date examples

参考

Tags : date java java 8

Java——如何检查一个字符串是否是数字

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-how-to-check-if-a-string-is-numeric/

几个 Java 例子向你展示如何检查一个字符串是否是数字。

1.Character.isDigit()

将一个字符串转换成一个char数组并用Character.isDigit()检查它

NumericExample.java

 package com.mkyong;

public class NumericExample {

    public static void main(String[] args) {

        System.out.println(isNumeric(""));          // false
        System.out.println(isNumeric(" "));         // false
        System.out.println(isNumeric(null));        // false
        System.out.println(isNumeric("1,200"));     // false
        System.out.println(isNumeric("1"));         // true
        System.out.println(isNumeric("200"));       // true
        System.out.println(isNumeric("3000.00"));   // false

    }

    public static boolean isNumeric(final String str) {

        // null or empty
        if (str == null || str.length() == 0) {
            return false;
        }

        for (char c : str.toCharArray()) {
            if (!Character.isDigit(c)) {
                return false;
            }
        }

        return true;

    }

} 

输出

 false
false
false
false
true
true
false 

2.Java 8

这个现在简单多了。

 public static boolean isNumeric(final String str) {

        // null or empty
        if (str == null || str.length() == 0) {
            return false;
        }

        return str.chars().allMatch(Character::isDigit);

    } 

3.Apache Commons Lang

如果 claspath 中存在 Apache Commons Lang,请尝试NumberUtils.isDigits()

pom.xml

 <dependency>
		<groupId>org.apache.commons</groupId>
		<artifactId>commons-lang3</artifactId>
		<version>3.9</version>
	</dependency> 
 import org.apache.commons.lang3.math.NumberUtils;

	public static boolean isNumeric(final String str) {

        return NumberUtils.isDigits(str);

    } 

4.NumberFormatException

此解决方案可以解决性能问题,但不推荐使用。

 public static boolean isNumeric(final String str) {

        if (str == null || str.length() == 0) {
            return false;
        }

        try {

            Integer.parseInt(str);
            return true;

        } catch (NumberFormatException e) {
            return false;
        }

    } 

参考

Java——如何将原始数组转换成列表

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-how-to-convert-a-primitive-array-to-list/

将原始数组int[]转换为List<Integer>的代码片段:

 int[] number = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

	List<Integer> list = new ArrayList<>();
	for (int i : number) {
    	list.add(i);
	} 

在 Java 8 中,您可以使用流 API 进行装箱和转换,如下所示:

 List<Integer> list = Arrays.stream(number).boxed().collect(Collectors.toList()); 

1.经典例子

将原始数组转换为列表的完整示例。

ArrayExample1.java

 package com.mkyong.array;

import java.util.ArrayList;
import java.util.List;

public class ArrayExample1 {

    public static void main(String[] args) {

        int[] number = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

        List<Integer> list = convertIntArrayToList(number);
        System.out.println("list : " + list);

    }

    private static List<Integer> convertIntArrayToList(int[] input) {

        List<Integer> list = new ArrayList<>();
        for (int i : input) {
            list.add(i);
        }
        return list;

    }
} 

输出

 list : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

Note
You can’t use the popular Arrays.asList to convert it directly, because boxing issue.

 int[] number = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
	// No, the return type is not what we want
	List<int[]> ints = Arrays.asList(number); 

2.Java 8 流

完整的 Java 8 流示例,用于将原始数组转换为列表。

ArrayExample2.java

 package com.mkyong.array;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class ArrayExample2 {

    public static void main(String[] args) {

        int[] number = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

        // IntStream.of or Arrays.stream, same output
        //List<Integer> list = IntStream.of(number).boxed().collect(Collectors.toList());

        List<Integer> list = Arrays.stream(number).boxed().collect(Collectors.toList());
        System.out.println("list : " + list);

    }
} 

输出

 list : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

参考

  1. IntStream JavaDoc
  2. Java–将数组转换成流

Tags : array intstream java8 list primitive stream

Java——如何将数组转换成流

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-how-to-convert-array-to-stream/

在 Java 8 中,可以使用Arrays.streamStream.of将数组转换成流。

1.对象数组

对于对象数组,Arrays.streamStream.of返回相同的输出。

TestJava8.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.stream.Stream;

public class TestJava8 {

    public static void main(String[] args) {

        String[] array = {"a", "b", "c", "d", "e"};

        //Arrays.stream
        Stream<String> stream1 = Arrays.stream(array);
        stream1.forEach(x -> System.out.println(x));

        //Stream.of
        Stream<String> stream2 = Stream.of(array);
        stream2.forEach(x -> System.out.println(x));
    }

} 

输出

a
b
c
d
e
a
b
c
d
e

查看 JDK 源代码。

Arrays.java

 /**
     * Returns a sequential {@link Stream} with the specified array as its
     * source.
     *
     * @param <T> The type of the array elements
     * @param array The array, assumed to be unmodified during use
     * @return a {@code Stream} for the array
     * @since 1.8
     */
    public static <T> Stream<T> stream(T[] array) {
        return stream(array, 0, array.length);
    } 

Stream.java

 /**
     * Returns a sequential ordered stream whose elements are the specified values.
     *
     * @param <T> the type of stream elements
     * @param values the elements of the new stream
     * @return the new stream
     */
    @SafeVarargs
    @SuppressWarnings("varargs") // Creating a stream from an array is safe
    public static<T> Stream<T> of(T... values) {
        return Arrays.stream(values);
    } 

Note
For object arrays, the Stream.of method is calling the Arrays.stream internally.

2.原始数组

对于原始数组,Arrays.streamStream.of将返回不同的输出。

TestJava8.java

 package com.mkyong.java8;

import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class TestJava8 {

    public static void main(String[] args) {

        int[] intArray = {1, 2, 3, 4, 5};

        // 1\. Arrays.stream -> IntStream 
        IntStream intStream1 = Arrays.stream(intArray);
        intStream1.forEach(x -> System.out.println(x));

        // 2\. Stream.of -> Stream<int[]>
        Stream<int[]> temp = Stream.of(intArray);

        // Cant print Stream<int[]> directly, convert / flat it to IntStream 
        IntStream intStream2 = temp.flatMapToInt(x -> Arrays.stream(x));
        intStream2.forEach(x -> System.out.println(x));

    }

} 

输出

1
2
3
4
5
1
2
3
4
5

查看 JDK 源代码。

Arrays.java

 /**
     * Returns a sequential {@link IntStream} with the specified array as its
     * source.
     *
     * @param array the array, assumed to be unmodified during use
     * @return an {@code IntStream} for the array
     * @since 1.8
     */
    public static IntStream stream(int[] array) {
        return stream(array, 0, array.length);
    } 

Stream.java

 /**
     * Returns a sequential {@code Stream} containing a single element.
     *
     * @param t the single element
     * @param <T> the type of stream elements
     * @return a singleton sequential stream
     */
    public static<T> Stream<T> of(T t) {
        return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
    } 

Which one?
For object arrays, both are calling the same Arrays.stream (refer example 1, JDK source code). For primitive arrays, I prefer Arrays.stream as well, because it returns fixed size IntStream directly, easier to manipulate it.

使用甲骨文 JDK 1.8.0_77 测试的 PS

参考

  1. 数组 JavaDoc
  2. 流 JavaDoc
  3. 如何打印一个数组,java 和 java 8 的例子

Java 创建并写入文件

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-how-to-create-and-write-to-a-file/

Java create and write file image

在 Java 中,我们可以使用Files.write来创建和写入文件。

 String content = "...";
	Path path = Paths.get("/home/mkyong/test.txt");

	// string -> bytes
	Files.write(path, content.getBytes(StandardCharsets.UTF_8)); 

Files.write也接受一个Iterable接口;这意味着这个 API 可以写一个List到一个文件中。

 List<String> list = Arrays.asList("a", "b", "c");
	Files.write(path, list); 

简史
在 Java 7 之前,对于将字节(镜像)写入文件,我们使用FileOutputStream;对于将字符(文本)写入文件,我们使用FileWriter,并且通常由BufferedWriter包装以获得性能。

  • 在 Java 7 中,有一个新的 NIO 类叫做java.nio.file.Files,我们可以用Files.write()来写字节和字符。
  • 在 Java 8 中,我们可以使用Files.newBufferedWriter(path)来创建一个BufferedWriter
  • 在 Java 11 中,有一个新的Files.writeString API 可以直接将字符串写入文件。

1.创建并写入文件–files . write

1.1 在 Java 7 之前,我们可以使用经典的FileWriterBufferedWriter将文本写入文件。

 try (FileWriter fw = new FileWriter(file);
       BufferedWriter bw = new BufferedWriter(fw)) {
      bw.write(content);
      bw.newLine();
  } 

在 Java 7 和更高版本中,我们可以使用一行Files.write将文本写入文件,并且我们也不用担心关闭打开的资源(文件),因为Files.write会自动关闭打开的资源。

 Files.write(path, content.getBytes(StandardCharsets.UTF_8)); 

1.2 以下示例使用Files.write创建一个String并将其写入文件。

FileWrite.java

 package com.mkyong.io.file;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.List;

public class FileWrite {

    private static final String NEW_LINE = System.lineSeparator();

    public static void main(String[] args) throws IOException {

        Path path = Paths.get("/home/mkyong/test/aaa.txt");
        writeFile(path, "Hello World 1" + NEW_LINE);

    }

    // Java 7
    private static void writeFile(Path path, String content)
				throws IOException {

        // file does not exist, create and write it
        // if the file exists, override the content
        Files.write(path, content.getBytes(StandardCharsets.UTF_8));

        // Append mode
        // if the file exists, append string to the end of file.
        // Files.write(path, content.getBytes(StandardCharsets.UTF_8),
				//	StandardOpenOption.CREATE, StandardOpenOption.APPEND);

        // if file does not exist, throws NoSuchFileException
        // if the file exists, append it
        // Files.write(path, content.getBytes(StandardCharsets.UTF_8),
				//	StandardOpenOption.APPEND);
    }
} 

输出

第一次运行时,我们创建了一个名为aaa.txt的文件。

/home/mkyong/test/aaa.txt

 Hello World 1 

运行第二次,我们将覆盖文件内容。

/home/mkyong/test/aaa.txt

 Hello World 1 

对于追加模式,我们可以同时定义StandardOpenOption.CREATEStandardOpenOption.APPEND

 Files.write(path, content.getBytes(StandardCharsets.UTF_8),
				StandardOpenOption.CREATE, StandardOpenOption.APPEND); 

运行第三次,这次启用追加模式,我们将把新内容追加到文件的末尾。

/home/mkyong/test/aaa.txt

 Hello World 1
Hello World 1 

1.3.Files.write也支持Iterable,这意味着我们可以通过一个List将多行写入一个文件。

 List<String> list = Arrays.asList("a", "b", "c");

	// Java 7
	Files.write(path, list, StandardCharsets.UTF_8);

  // Java 8, default utf_8
  Files.write(path, list); 

2.Java 11–files . writestring

在 Java 7 中,我们需要在将String传递给Files.write之前将其转换成byte[]

 String content = "...";
	Files.write(path, content.getBytes(StandardCharsets.UTF_8)); 

在 Java 11 中,我们可以使用名为Files.writeString的新 API 将String或文本直接写入文件。

 // Java 11
  private static void writeFileJava11(Path path, String content)
			throws IOException {

      // default utf_8
      // file does not exists, create and write it
      // if the file exists, override the content
      Files.writeString(path, content);

      // Append mode
      // Files.writeString(path, content,
			//	StandardOpenOption.CREATE, StandardOpenOption.APPEND);
  } 

3.FileWriter + BufferedWriter

3.1 在 Java 7 之前,FileWriter + BufferedWriter组合是创建字符或文本并将其写入文件的标准解决方案。

 try (FileWriter fw = new FileWriter(file);
       BufferedWriter bw = new BufferedWriter(fw)) {
      bw.write(content);
      bw.newLine(); // add new line, System.lineSeparator()
  }

	 // append mode
  try (FileWriter fw = new FileWriter(file, true);
       BufferedWriter bw = new BufferedWriter(fw)) {
      bw.write(content);
      bw.newLine();
  } 

3.2 在 Java 8 中,我们可以使用Files.newBufferedWriter直接创建一个BufferedWriter对象。

 // default utf_8
  try (BufferedWriter bw = Files.newBufferedWriter(path)) {
      bw.write(content);
      bw.newLine();
  }

  // append mode
  try (BufferedWriter bw = Files.newBufferedWriter(path,
          StandardOpenOption.CREATE, StandardOpenOption.APPEND)) {
      bw.write(content);
      bw.newLine();
  } 

P.S 上面的FileWriter + BufferedWriter方法写文件没有错,只是Files.write提供了更干净易用的 API。

4.文件输出流

在 Java 中,我们使用FileOutputStream将原始字节写入文件,就像图像一样。

 private static void writeFile(File file, byte[] bytes) throws IOException {

      try (FileOutputStream fos = new FileOutputStream(file)) {
          fos.write(bytes);
      }

      // append mode
      /*try (FileOutputStream fos = new FileOutputStream(file, true)) {
          fos.write(content.getBytes(StandardCharsets.UTF_8));
      }*/

  } 

下载源代码

$ git 克隆https://github.com/mkyong/core-java

$ cd java-io

参考

Java——如何获取当前日期时间

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-how-to-get-current-date-time-date-and-calender/

在本教程中,我们将向您展示如何从新的 Java 8 java.time.*中获取当前日期时间,如 LocaldateLocalTimeLocalDateTimeZonedDateTimeInstant ,以及旧的日期时间 API,如 DateCalendar

目录

摘要

  • 对于新的 Java 8java.time.*API,我们可以使用.now()获取当前的日期时间,并用 DateTimeFormatter 对其进行格式化。
  • 对于遗留的日期时间 API,我们可以使用new Date()Calendar.getInstance()来获取当前的日期时间,并用 SimpleDateFormat 对其进行格式化。

1。用 Java 获取当前日期时间

下面是一些用 Java 显示当前日期时间的代码片段。

对于java.time.LocalDate,使用LocalDate.now()

 DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu/MM/dd");
  LocalDate localDate = LocalDate.now();
  System.out.println(dtf.format(localDate));            // 2021/03/22 

对于java.time.localTime,使用LocalTime.now()

 DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HH:mm:ss");
  LocalTime localTime = LocalTime.now();
  System.out.println(dtf.format(localTime));            // 16:37:15 

对于java.time.LocalDateTime,使用LocalDateTime.now()

 DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu/MM/dd HH:mm:ss");
  LocalDateTime now = LocalDateTime.now();
  System.out.println(dtf.format(now));                  //  2021/03/22 16:37:15 

对于java.time.ZonedDateTime,使用ZonedDateTime.now()

 // get current date-time, with system default time zone
  DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu/MM/dd HH:mm:ss");
  ZonedDateTime now = ZonedDateTime.now();
  System.out.println(dtf.format(now));                  // 2021/03/22 16:37:15
  System.out.println(now.getOffset());                  // +08:00

  // get current date-time, with a specified time zone
  ZonedDateTime japanDateTime = now.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
  System.out.println(dtf.format(japanDateTime));        // 2021/03/22 17:37:15
  System.out.println(japanDateTime.getOffset());        // +09:00 

对于java.time.Instant,使用Instant.now()

 Instant now = Instant.now();

  // convert Instant to ZonedDateTime
  DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu/MM/dd HH:mm:ss");
  ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(now, ZoneId.systemDefault());
  System.out.println(dtfDateTime.format(zonedDateTime)); 

对于java.util.Date,使用new Date()

 DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
  Date date = new Date();
  System.out.println(dateFormat.format(date));           // 2021/03/22 16:37:15 

对于java.util.Calendar,使用Calendar.getInstance()

 DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
  Calendar cal = Calendar.getInstance();
  System.out.println(dateFormat.format(cal.getTime()));  // 2021/03/22 16:37:15 

2 .java.time.LocalDate

对于java.time.LocalDate,使用LocalDate.now()获取不带时区的当前日期,并用DateTimeFormatter对其进行格式化。

LocalDateExample.java

 package com.mkyong.app;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class LocalDateExample {

  public static void main(String[] args) {

      DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu/MM/dd");
      LocalDate localDate = LocalDate.now();
      System.out.println(dtf.format(localDate));    // 2021/03/22

  }

} 

输出

Terminal

 2021/03/22 

3。java.time.LocalTime

对于java.time.LocalTime,使用LocalDate.now()获取不带时区的当前时间,并用DateTimeFormatter对其进行格式化。

LocalTimeExample.java

 package com.mkyong.app;

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

public class LocalTimeExample {

    public static void main(String[] args) {

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HH:mm:ss");
        LocalTime localTime = LocalTime.now();
        System.out.println(dtf.format(localTime));    // 16:37:15

    }

} 

输出

Terminal

 16:37:15 

4 .Java . time . localdatetime

对于java.time.LocalDateTime,使用LocalDateTime.now()获取不带时区的当前日期时间,并用DateTimeFormatter对其进行格式化。

LocalDateTimeExample.java

 package com.mkyong.app;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class LocalDateTimeExample {

    public static void main(String[] args) {

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu/MM/dd HH:mm:ss");
        LocalDateTime now = LocalDateTime.now();
        System.out.println(dtf.format(now));        //  2021/03/22 16:37:15

    }

} 

输出

Terminal

 2021/03/22 16:37:15 

5. java.time.ZonedDateTime

对于java.time.ZonedDateTime,使用ZonedDateTime.now()获取系统默认时区或指定时区的当前日期时间。

ZonedDateTimeExample.java

 package com.mkyong.app;

import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class ZonedDateTimeExample {

  public static void main(String[] args) {

      DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu/MM/dd HH:mm:ss");

      // Get default time zone
      System.out.println(ZoneOffset.systemDefault());         // Asia/Kuala_Lumpur
      System.out.println(OffsetDateTime.now().getOffset());   // +08:00

      // get current date time, with +08:00
      ZonedDateTime now = ZonedDateTime.now();
      System.out.println(dtf.format(now));                    // 2021/03/22 16:37:15
      System.out.println(now.getOffset());                    // +08:00

      // get get current date time, with +09:00
      ZonedDateTime japanDateTime = now.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
      System.out.println(dtf.format(japanDateTime));          // 2021/03/22 17:37:15
      System.out.println(japanDateTime.getOffset());          // +09:00

  }

} 

输出

Terminal

 Asia/Kuala_Lumpur
+08:00

2021/03/22 16:37:15
+08:00

2021/03/22 17:37:15
+09:00 

6。java.time.Instant

对于java.time.Instant,使用Instant.now()获取自 Unix 纪元时间(UTC 1970 年 1 月 1 日午夜)以来经过的秒数,然后转换为其他java.time.*日期时间类,如LocalDateLocalDateTimeZonedDateTime

InstantExample.java

 package com.mkyong.app;

import java.time.*;
import java.time.format.DateTimeFormatter;

public class InstantExample {

  private static final DateTimeFormatter dtfDate = DateTimeFormatter.ofPattern("uuuu/MM/dd");
  private static final DateTimeFormatter dtfTime = DateTimeFormatter.ofPattern("HH:mm:ss");
  private static final DateTimeFormatter dtfDateTime = DateTimeFormatter.ofPattern("uuuu/MM/dd HH:mm:ss");

  public static void main(String[] args) {

      // seconds passed since the Unix epoch time (midnight of January 1, 1970 UTC)
      Instant now = Instant.now();

      // convert Instant to LocalDate
      LocalDate localDate = LocalDate.ofInstant(now, ZoneId.systemDefault());
      System.out.println(dtfDate.format(localDate));

      // convert Instant to localTime
      LocalTime localTime = LocalTime.ofInstant(now, ZoneId.systemDefault());
      System.out.println(dtfTime.format(localTime));

      // convert Instant to LocalDateTime
      LocalDateTime localDateTime = LocalDateTime.ofInstant(now, ZoneId.systemDefault());
      System.out.println(dtfDateTime.format(localDateTime));

      // convert Instant to ZonedDateTime
      ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(now, ZoneId.systemDefault());
      System.out.println(dtfDateTime.format(zonedDateTime));

  }

} 

输出

Terminal

 2021/03/22
16:37:15
2021/03/22 16:37:15
2021/03/22 16:37:15 

7。java.util.Date(旧版)

对于传统的java.util.Date,使用new Date()new Date(System.currentTimeMillis()获取当前日期时间,并用SimpleDateFormat对其进行格式化。

DateExample.java

 package com.mkyong.app;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateExample {

  public static void main(String[] args) {

      DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

      Date date = new Date();
      System.out.println(dateFormat.format(date));    // 2021/03/22 16:37:15

      // new Date() actually calls this new Date(long date)
      Date date2 = new Date(System.currentTimeMillis());
      System.out.println(dateFormat.format(date));    // 2021/03/22 16:37:15

  }

} 

输出

Terminal

 2021/03/22 16:37:15
  2021/03/22 16:37:15 

8。java.util.Calendar(旧版)

对于传统的java.util.Calendar,使用Calendar.getInstance()获取当前日期时间,并用SimpleDateFormat对其进行格式化。

CalendarExample.java

 package com.mkyong.app;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class CalendarExample {

  public static void main(String[] args) {

      DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
      Calendar cal = Calendar.getInstance();
      System.out.println(dateFormat.format(cal.getTime()));   // 2021/03/22 16:37:15

  }

} 

输出

Terminal

 2021/03/22 16:37:15 

9。参考文献

Java——如何从 Map 中获取键和值

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-how-to-get-keys-and-values-from-map/

在 Java 中,我们可以通过map.entrySet()获得键和值

 Map<String, String> map = new HashMap<>();

	// Get keys and values
	for (Map.Entry<String, String> entry : map.entrySet()) {
		String k = entry.getKey();
		String v = entry.getValue();
		System.out.println("Key: " + k + ", Value: " + v);
	}

	// Java 8
	map.forEach((k, v) -> {
		System.out.println("Key: " + k + ", Value: " + v);
	}); 

完整的例子。

JavaMapExample.java

 package com.mkyong;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class JavaMapExample {

    public static void main(String[] args) {

        Map<String, String> map = new HashMap<>();
        map.put("db", "oracle");
        map.put("username", "user1");
        map.put("password", "pass1");

        // Get keys and values
        for (Map.Entry<String, String> entry : map.entrySet()) {
            String k = entry.getKey();
            String v = entry.getValue();
            System.out.println("Key: " + k + ", Value: " + v);
        }

        // Get all keys
        Set<String> keys = map.keySet();
        for (String k : keys) {
            System.out.println("Key: " + k);
        }

        // Get all values
        Collection<String> values = map.values();
        for (String v : values) {
            System.out.println("Value: " + v);
        }

        // Java 8
        map.forEach((k, v) -> {
            System.out.println("Key: " + k + ", Value: " + v);
        });

    }
} 

输出

 Key: password, Value: pass1
Key: db, Value: oracle
Key: username, Value: user1

Key: password
Key: db
Key: username

Value: pass1
Value: oracle
Value: user1

Key: password, Value: pass1
Key: db, Value: oracle
Key: username, Value: user1 

参考

Java–如何获得新的行字符或\n?

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-how-to-get-new-line-character-or-n/

换行符,也称为行尾(EOL)、换行符、换行符、行分隔符或回车符,是一个控制符,用来告知一行文本的结束,下一个字符应该从新行开始。在 Windows 系统上是\r\n,在 Linux 系统上是\n

在 Java 中,我们可以使用 System.lineSeparator() 来获取一个与平台相关的换行符。

GetNewLine.java

 package com.mkyong.io.howto;

public class GetNewLine {

    public static void main(String[] args) {

        System.out.print("Line 1");

        // Windows \r\n, Linux \n
        System.out.print(System.lineSeparator());

        System.out.print("Line 2");

    }
} 

输出

 Line 1
Line 2 

P . SSystem.getProperty("line.separator")也返回相同的结果。

1.System.lineSeparator()

下面是从 Java 1.7 开始可用的System.lineSeparator()方法签名,请阅读注释。

System.java

 package java.lang;

public final class System {

  /**
   * Returns the system-dependent line separator string.  It always
   * returns the same value - the initial value of the {@linkplain
   * #getProperty(String) system property} {@code line.separator}.
   *
   * <p>On UNIX systems, it returns {@code "\n"}; on Microsoft
   * Windows systems it returns {@code "\r\n"}.
   *
   * @return the system-dependent line separator string
   * @since 1.7
   */
  public static String lineSeparator() {
      return lineSeparator;
  } 

2.打印换行符

如果我们想打印一个平台相关的新行字符,尝试在 String.format 中的%n(行分隔符)。

GetNewLine2.java

 package com.mkyong.io.howto;

public class GetNewLine2 {

    public static void main(String[] args) {

        System.out.print(String.format("%s%n%s", "Line 1", "Line 2"));

    }
} 

输出

 Line 1
Line 2 

3.写一个换行符

如果我们使用BufferedWriter向文件中写入文本,那么newLine()代表平台相关的换行符。

GetNewLine3.java

 package com.mkyong.io.howto;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class GetNewLine3 {

    public static void main(String[] args) {

        // write a new line character
        String fileName = "/home/mkyong/sample.txt";

        List<String> content = Arrays.asList("A", "B", "C");

        try (BufferedWriter bw = new BufferedWriter(new FileWriter(fileName))) {

            for (String t : content) {
                bw.write(t);
                bw.newLine();
                // same
                //bw.write(System.lineSeparator());
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

    }
} 

审查newLine()方法签名,在内部,BufferedWriter也使用System.lineSeparator()

BufferedWriter.java

 package java.io;

public class BufferedWriter extends Writer {
    /**
     * Writes a line separator.  The line separator string is defined by the
     * system property {@code line.separator}, and is not necessarily a single
     * newline ('\n') character.
     *
     * @exception  IOException  If an I/O error occurs
     */
    public void newLine() throws IOException {
        write(System.lineSeparator());
    }

    //...
} 

下载源代码

$ git 克隆https://github.com/mkyong/core-java

$ cd java-io

参考

Java——如何连接数组

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-how-to-join-arrays/

在本文中,我们将向您展示几种加入 Java 数组的方法。

  1. Apache Commons Lang–ArrayUtils
  2. Java API
  3. Java 8 流

1.Apache Commons Lang–ArrayUtils

最简单的方法是添加 Apache Commons Lang 库,并使用ArrayUtils. addAll加入数组。此方法支持基元和对象类型数组。

JoinArray.java

 package com.mkyong.example.array;

import org.apache.commons.lang3.ArrayUtils;

import java.util.Arrays;

public class JoinArray {

    public static void main(String[] args) {

        String[] s1 = new String[]{"a", "b", "c"};
        String[] s2 = new String[]{"d", "e", "f"};

        String[] result = ArrayUtils.addAll(s1, s2);

        System.out.println(Arrays.toString(result));

		int [] int1 = new int[]{1,2,3};
        int[] int2 = new int[]{4,5,6};

        int[] result2 = ArrayUtils.addAll(int1, int2);

        System.out.println(Arrays.toString(result2));

    }

} 

输出

[a, b, c, d, e, f]
[1, 2, 3, 4, 5, 6]

对于 Maven 用户。

pom.xml

 <dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.4</version>
</dependency> 

2.Java API

纯 Java API 示例,支持原语和泛型类型。

JoinArray.java

 package com.mkyong.example.array;

import java.lang.reflect.Array;
import java.util.Arrays;

public class JoinArray {

    public static void main(String[] args) {

        String[] s1 = new String[]{"a", "b", "c"};
        String[] s2 = new String[]{"d", "e", "f"};
        String[] s3 = new String[]{"g", "h", "i"};

        String[] result = joinArrayGeneric(s1, s2, s3);

        System.out.println(Arrays.toString(result));

        int[] int1 = new int[]{1, 2, 3};
        int[] int2 = new int[]{4, 5, 6};
        int[] int3 = new int[]{7, 8, 9};

        int[] result2 = joinArray(int1, int2, int3);

        System.out.println(Arrays.toString(result2));

    }

    static <T> T[] joinArrayGeneric(T[]... arrays) {
        int length = 0;
        for (T[] array : arrays) {
            length += array.length;
        }

        //T[] result = new T[length];
        final T[] result = (T[]) Array.newInstance(arrays[0].getClass().getComponentType(), length);

        int offset = 0;
        for (T[] array : arrays) {
            System.arraycopy(array, 0, result, offset, array.length);
            offset += array.length;
        }

        return result;
    }

    static int[] joinArray(int[]... arrays) {
        int length = 0;
        for (int[] array : arrays) {
            length += array.length;
        }

        final int[] result = new int[length];

        int offset = 0;
        for (int[] array : arrays) {
            System.arraycopy(array, 0, result, offset, array.length);
            offset += array.length;
        }

        return result;
    }

	//create other overloaded primitive type - long, double...
	//static long[] joinArray(long[]... arrays) 
} 

输出

[a, b, c, d, e, f, g, h, i]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

3.Java 8 流

Java 8 流连接数组的例子。

JoinArray.java

 package com.mkyong.example.array;

import java.util.Arrays;

import java.util.stream.IntStream;
import java.util.stream.Stream;

public class JoinArray {

    public static void main(String[] args) {

        String[] s1 = new String[]{"a", "b", "c"};
        String[] s2 = new String[]{"d", "e", "f"};
        String[] s3 = new String[]{"g", "h", "i"};

		//join object type array
        String[] result = Stream.of(s1, s2, s3).flatMap(Stream::of).toArray(String[]::new);
        System.out.println(Arrays.toString(result));

        int [] int1 = new int[]{1,2,3};
        int[] int2 = new int[]{4,5,6};
        int[] int3 = new int[]{7,8,9};

		//join 2 primitive type array
        int[] result2 = IntStream.concat(Arrays.stream(int1), Arrays.stream(int2)).toArray();

		//join 3 primitive type array, any better idea?
        int[] result3 = IntStream.concat(Arrays.stream(int1), 
			IntStream.concat(Arrays.stream(int2), Arrays.stream(int3))).toArray();

        System.out.println(Arrays.toString(result2));

        System.out.println(Arrays.toString(result3));

    }

} 

输出

[a, b, c, d, e, f, g, h, i]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

有更好的 Java 8 流例子吗?请在下面评论。

参考

  1. Apache Commons Lang–ArrayUtils
  2. Java 8 Stream JavaDoc
  3. Java 8:用 IntStreams 代替传统的 for 循环
  4. Java 8 流教程

Tags : array java java8 stream

Java–如何用逗号连接列表字符串

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-how-to-join-list-string-with-commas/

在 Java 中,我们可以使用String.join(",", list)用逗号连接一个列表字符串。

1.Java 8

1.1 String.join

JavaStringExample1.java

 package com.mkyong;

import java.util.Arrays;
import java.util.List;

public class JavaStringExample1 {

    public static void main(String[] args) {

        List<String> list = Arrays.asList("a","b","c");
        String result = String.join(",", list);

        System.out.println(result);

    }

} 

输出

 a,b,c 

1.2 流Collectors.joining

JavaStringExample2.java

 package com.mkyong;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class JavaStringExample2 {

    public static void main(String[] args) {

        List<String> list = Arrays.asList("a", "b", "c");

        String result = list.stream().collect(Collectors.joining(","));

        System.out.println(result);

    }

} 

输出

 a,b,c 

2.在过去

创建一个自定义方法来手动连接带分隔符的字符串。

JavaStringExample3.java

 package com.mkyong;

import java.util.Arrays;
import java.util.List;

public class JavaStringExample3 {

    public static void main(String[] args) {

        System.out.println(join(",", Arrays.asList("a")));
        System.out.println(join(",", Arrays.asList("a", "b")));
        System.out.println(join(",", Arrays.asList("a", "b", "c")));
        System.out.println(join(",", Arrays.asList("")));
        System.out.println(join(",", null));

    }

    private static String join(String separator, List<String> input) {

        if (input == null || input.size() <= 0) return "";

        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < input.size(); i++) {

            sb.append(input.get(i));

            // if not the last item
            if (i != input.size() - 1) {
                sb.append(separator);
            }

        }

        return sb.toString();

    }

} 

输出

 a
a,b
a,b,c
//empty 

参考

  1. Java 8–string joiner 示例

Java——如何将一个名字打印 10 次?

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-how-to-print-a-name-10-times/

这篇文章向你展示了打印一个名字十次的不同方法。

1.环

1.1 For 循环

JavaSample1.java

 package com.mkyong.samples;

public class JavaSample1 {

    public static void main(String[] args) {

        for (int i = 0; i < 10; i++) {
            System.out.println("Java ");
        }

    }

} 

输出

 Java
Java
Java
Java
Java
Java
Java
Java
Java
Java 

1.2 While 循环

JavaSample2.java

 package com.mkyong.samples;

public class JavaSample2 {

    public static void main(String[] args) {

        int i = 0;
        while (i < 10) {
            System.out.println("Java");
            i++;
        }

    }

} 

2.阅读和打印

这个例子将从控制台读取输入并打印十次。

JavaSampleReadPrint.java

 package com.mkyong.samples;

import java.util.Scanner;

public class JavaSampleReadPrint {

    public static void main(String[] args) {

        String name = "";
        // read an input and print 10 times
        try (Scanner in = new Scanner(System.in)) {
            System.out.print("Your name: ");
            name = in.nextLine();
        }

        for (int i = 0; i < 10; i++) {
            System.out.println(name);
        }
    }

} 

输出

 Your name: mkyong
mkyong
mkyong
mkyong
mkyong
mkyong
mkyong
mkyong
mkyong
mkyong
mkyong 

3.递归

这个例子将使用递归循环。

JavaSampleReadRecursion.java

 package com.mkyong.samples;

public class JavaSampleReadRecursion {

    public static void main(String[] args) {

        print("mkyong", 10);

    }

    static void print(String name, int times) {

        System.out.println(times + ":" + name);

        if (times > 1) {
            print(name, times - 1);
        }
    }

} 

输出

 10:mkyong
9:mkyong
8:mkyong
7:mkyong
6:mkyong
5:mkyong
4:mkyong
3:mkyong
2:mkyong
1:mkyong 

4.没有循环,没有递归

这个例子很有趣,它打印一个字符串 1000 次没有循环,只是简单的数学。

JavaNoLoop.java

 package com.mkyong.samples;

public class JavaNoLoop {

    public static void main(String[] args) {

        String s1 = "Java\n";
        String s3 = s1 + s1 + s1;
        String s10 = s3 + s3 + s3 + s1;
        String s30 = s10 + s10 + s10;
        String s100 = s30 + s30 + s30 + s10;
        String s300 = s100 + s100 + s100;
        String s1000 = s300 + s300 + s300 + s100;
        System.out.print(s1000);

    }

} 

5.字符+字符串并替换

JavaCharStrReplace.java

 package com.mkyong.samples;

public class JavaCharStrReplace {

    public static void main(String[] args) {

        char[] chars = new char[10];
        String str = new String(chars);
        System.out.print(str.replace("\0", "Mkyong\n"));

    }
} 

6.Java 8 字符串连接

6.1 Collections.nCopiesString.join

JavaStringJoin.java

 package com.mkyong.samples;

import java.util.Collections;

public class JavaStringJoinNCopies {

    public static void main(String[] args) {

        System.out.print(String.join("\n", Collections.nCopies(10, "Mkyong")));

    }
} 

6.2 Arrays.fillString.join

JavaStringJoinArray.java

 package com.mkyong.samples;

import java.util.Arrays;

public class JavaStringJoinArray {

    public static void main(String[] args) {

        String[] str = new String[10];
        Arrays.fill(str, "Mkyong");
        System.out.println(String.join("\n", str));

    }
} 

7.Java 8 IntStream.range

JavaIntStream.java

 package com.mkyong.samples;

import java.util.stream.IntStream;

public class JavaIntStream {

    public static void main(String[] args) {

        IntStream.range(0,10).forEach(x->System.out.println("Mkyong"));

    }
} 

8.Java 11 重复

Java11Repeat.java

 package com.mkyong.samples;

public class Java11Repeat {

    public static void main(String[] args) {

        String str = "Mkyong\n";
        System.out.println(str.repeat(10));

    }
} 

参考

Java——如何打印金字塔

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-how-to-print-a-pyramid/

一个 Java 例子,打印半金字塔和全金字塔,好玩。

CreatePyramid.java

 package com.mkyong;

import java.util.Collections;

public class CreatePyramid {

    public static void main(String[] args) {

        int rows = 5;

        System.out.println("\n1\. Half Pyramid\n");
        for (int i = 0; i < rows; i++) {

            for (int j = 0; j <= i; j++) {
                System.out.print("*");
            }

            System.out.println("");
        }

        System.out.println("\n2\. Full Pyramid\n");
        for (int i = 0; i < rows; i++) {

            for (int j = 0; j < rows - i; j++) {
                System.out.print(" ");
            }

            for (int k = 0; k <= i; k++) {
                System.out.print("* ");
            }

            System.out.println("");
        }

        //java 8 , one line
        System.out.println("\n3\. Full Pyramid (Compact)\n");
        for (int i = 0; i < rows; i++) {

            System.out.println(String.join("", Collections.nCopies(5 - i - 1, " "))
                    + String.join("", Collections.nCopies(2 * i + 1, "*")));

        }

        // java 8
        System.out.println("\n4\. Inverted Pyramid\n");
        for (int i = rows; i > 0; i--) {

            System.out.println(String.join("", Collections.nCopies(5 - i, " "))
                    + String.join("", Collections.nCopies(2 * i - 1, "*")));

        }

    }

} 

输出

 1\. Half Pyramid

*
**
***
****
*****

2\. Full Pyramid

     * 
    * * 
   * * * 
  * * * * 
 * * * * * 

3\. Full Pyramid (Compact)

    *
   ***
  *****
 *******
*********

4\. Inverted Pyramid

*********
 *******
  *****
   ***
    * 

参考

  1. collections . n copies JavaDoc
  2. Python–打印金字塔

如何用 Java 读取文件

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-how-to-read-a-file/

本文重点介绍几种在 Java 中读取文件的常用方法。

  1. Files.lines,返回一个Stream (Java 8)
  2. Files.readString,返回一个String (Java 11),最大文件大小 2G。
  3. Files.readAllBytes,返回一个byte[] (Java 7),最大文件大小 2G。
  4. Files.readAllLines,返回一个List<String> (Java 8)
  5. BufferedReader,经典老朋友(Java 1.1 - >永远)
  6. Scanner (Java 1.5)

新的 Java 8 Files.lines在读取小型或大型文本文件方面表现良好,返回一个Stream(灵活的类型并支持并行),自动关闭资源,并且有一行干净的代码。

 Stream<String> lines = Files.lines(Paths.get(fileName)); 

在现代 Java 8+中,我们应该使用Files.lines来读取一个文本文件。


简单来说,小档案阅读没有太大区别,只是回归类型的味道。对于读取大文件,选择 Java 8 Files.lines的流和并行特性或经典的BufferedReader

文本文件

这里有一个简单的文本文件,只包含五行。其余的 Java 示例将会读取这个文件。

src/main/resources/app.log

 Line 1
Line 2
Line 3
Line 4
Line 5 

1.Files.lines (Java 8)

1.1 本例使用 Java 8 Files.lines将上述文件读入一个Stream,并逐行打印。此外,Files.lines将帮助自动关闭打开的资源(文件);我们不需要用 try-with-resources 包装代码。

ReadFile1.java

 package com.mkyong.io.file;

import com.mkyong.io.utils.ResourceHelper;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;

public class ReadFile1 {

    public static void main(String[] args) throws IOException {

        String fileName = ResourceHelper.getAbsoluteFilePath("app.log");

        // auto-close the resources
        Stream<String> lines = Files.lines(Paths.get(fileName));

        // does not preserve order
        lines.forEach(System.out::println);

        // preserve order
        // lines.forEachOrdered(System.out::println);

    }

} 

输出

Terminal

 Line 1
Line 2
Line 3
Line 4
Line 5 

1.2 为了读入一个小的文本文件,我们可以使用collect很容易地将流转换成List<String>

 String fileName = ResourceHelper.getAbsoluteFilePath("app.log");

  Stream<String> lines = Files.lines(Paths.get(fileName));

  // only for small text file
  List<String> collect = lines.collect(Collectors.toList()); 

1.3 对于在大型文本文件中读取,如果行的顺序不重要,我们可以打开流的parallel功能来进一步提高读取速度。

 // a large text file, for example, 10G
  String fileName = "/home/mkyong/large.txt";

  Stream<String> lines = Files.lines(Paths.get(fileName));

  // parallel
  lines.parallel().forEach(l -> {/* do work */}); 

1.4 一个常见的错误是直接把大的Stream转换成List,如果流大小大于正在运行的 JVM 堆大小就会抛出java.lang.OutOfMemoryError: Java heap space

 // a large text file, for example, 10G
  String fileName = "/home/mkyong/large.txt";

  Stream<String> lines = Files.lines(Paths.get(fileName));

  // java.lang.OutOfMemoryError: Java heap space
  List<String> collect = lines.collect(Collectors.toList()); 

1.5 最后一个lines.forEach,不保持行的顺序,如果我们想保持顺序就试试lines.forEachOrdered

 Stream<String> lines = Files.lines(Paths.get(fileName));

  // does not preserve order
  lines.forEach(System.out::println);

  // preserve order
  lines.forEachOrdered(System.out::println); 

2.Files.readString (Java 11)

2.1 这个Files.readString()将一个文件读入一个字符串,如果读取的文件大小超过 2G,就会抛出java.lang.OutOfMemoryError: Required array size too large

ReadFile2.java

 package com.mkyong.io.file;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class ReadFile2 {

    public static void main(String[] args) throws IOException {

        String fileName = "/home/mkyong/large.txt";

        // default UTF_8
        String s = Files.readString(Paths.get(fileName));
        System.out.println(s);

        // String s = Files.readString(Paths.get(fileName), StandardCharsets.UTF_8);
    }
} 

2.2 查看源代码,新的 Java 11 readString,内部使用已有的 Java 7 readAllBytes将一个文件读入一个byte[]JLA.newStringNoReplbyte[]转换回一个字符串。

Files.java

 package java.nio.file;

  public final class Files {

    public static String readString(Path path, Charset cs) throws IOException {
          Objects.requireNonNull(path);
          Objects.requireNonNull(cs);

          byte[] ba = readAllBytes(path);

          if (path.getClass().getModule() != Object.class.getModule())
              ba = ba.clone();
          return JLA.newStringNoRepl(ba, cs);
    }

    //...
} 

3.Files.readAllBytes (Java 7)

3.1 本例使用Files.readAllBytes将一个文件读入一个字节数组byte[],如果读取的文件大小超过 2G,就会抛出java.lang.OutOfMemoryError: Required array size too large

ReadFile3.java

 import com.mkyong.io.utils.ResourceHelper;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

public class ReadFile3 {

    public static void main(String[] args) throws IOException {

        String fileName = "/home/mkyong/app.log";

        byte[] bytes = Files.readAllBytes(Paths.get(fileName));
        String content = new String(bytes, StandardCharsets.UTF_8);
        System.out.println(content);

    }
} 

4.Files.readAllLines (Java 8)

4.1 这个例子使用Files.readAllLines将一个文件读入一个List<String>,如果文件大小大于正在运行的 JVM 堆大小,就会抛出java.lang.OutOfMemoryError: Java heap space

ReadFile4.java

 package com.mkyong.io.file;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

public class ReadFile4 {

    public static void main(String[] args) throws IOException {

        String fileName = "/home/mkyong/app.log";

        List<String> lines = Files.readAllLines(Paths.get(fileName),
                                                  StandardCharsets.UTF_8);
        lines.forEach(System.out::println);

    }
} 

5.buffer eader(Java 1.1)

5.1 一个经典的老朋友,BufferedReader的例子,在读取小文件和大文件时工作良好,默认的缓冲区大小(8k)对于大多数目的来说足够大了。

ReadFile5a.java

 package com.mkyong.io.file;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class ReadFile5a {

    public static void main(String[] args) throws IOException {

        String fileName = "/home/mkyong/app.log";

        // defaultCharBufferSize = 8192; or 8k
        try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        }

    }
} 

5.2 我们可以指定缓冲区的大小。

ReadFile5b.java

 package com.mkyong.io.file;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class ReadFile5b {

    public static void main(String[] args) throws IOException {

        String fileName = "/home/mkyong/app.log";

        int bufferSize = 10240; //10k
        try (BufferedReader br = new BufferedReader(
                      new FileReader(fileName), bufferSize)) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        }
    }
} 

5.3 在 Java 8 中,我们可以使用新的Files.newBufferedReader来创建一个BufferedReader

 try (BufferedReader br = Files.newBufferedReader(Paths.get(fileName))) {
      String line;
      while ((line = br.readLine()) != null) {
          System.out.println(line);
      }
  } 

查看源代码,没什么特别的。

Files.java

 package java.nio.file;

public final class Files {

    public static BufferedReader newBufferedReader(Path path, Charset cs)
          throws IOException
      {
          CharsetDecoder decoder = cs.newDecoder();
          Reader reader = new InputStreamReader(newInputStream(path), decoder);
          return new BufferedReader(reader);
      }

    //
} 

阅读这个-Java 如何用 BufferedReader 读取文件

5.4 对于自引用,一个经典的 try catch finally 手动关闭一个打开的文件。

ReadFile5c.java

 package com.mkyong.io.file;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class ReadFile5c {

    public static void main(String[] args) throws IOException {

        String fileName = "/home/mkyong/app.log";

        BufferedReader br = null;
        FileReader fr = null;

        try {

            fr = new FileReader(fileName);
            br = new BufferedReader(fr);

            // read line by line
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }

        } catch (IOException e) {
            System.err.format("IOException: %s%n", e);
        } finally {
            try {
                if (br != null)
                    br.close();

                if (fr != null)
                    fr.close();
            } catch (IOException ex) {
                System.err.format("IOException: %s%n", ex);
            }
        }

    }
} 

6.扫描仪(Java 1.5)

6.1 在Scanner类中,delimiter特性对于读取和过滤小文件仍然很有用。Java 9 和 Java 10 增加了像findAll和构造函数这样的新方法来改进Scanner类。然而,对于读取大文件,这个Scanner类比BufferedReader慢。

ReadFile6.java

 package com.mkyong.io.file;

import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;

public class ReadFile6 {

    public static void main(String[] args) throws IOException {

        String fileName = "/home/mkyong/app.log";

        try (Scanner sc = new Scanner(new FileReader(fileName))) {
            while (sc.hasNextLine()) {
                String line = sc.nextLine();
            }
        }

    }
} 

下载源代码

$ git 克隆https://github.com/mkyong/core-java

$ cd java-io

参考

Java——如何将字符串保存到文件中

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-how-to-save-a-string-to-a-file/

在 Java 中,有许多方法可以将字符串写入文件。

1.Java 11–files . writestring

最后,在java.nio中增加了一个新方法,可以轻松地将字符串保存到File中。

StringToFileJava11.java

 package com.mkyong;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class StringToFileJava11 {

    public static void main(String[] args) {

        String content = "Hello World \r\nJava!\r\n";
        String path = "c:\\projects\\app.log";

        try {

            // Java 11 , default StandardCharsets.UTF_8
            Files.writeString(Paths.get(path), content);

            // encoding
            // Files.writeString(Paths.get(path), content, StandardCharsets.US_ASCII);

            // extra options
            // Files.writeString(Paths.get(path), content, 
			//		StandardOpenOption.CREATE, StandardOpenOption.APPEND);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

} 

c:\projects\app.log

 Hello World 
Java! 

2.Java 7–文件.写入

StringToFileJava7.java

 package com.mkyong;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class StringToFileJava7 {

    public static void main(String[] args) {

        String content = "Hello World \r\nJava!\r\n";
        String path = "c:\\projects\\app.log";

        try {

            // Java 7
            Files.write(Paths.get(path), content.getBytes());

            // encoding
            // Files.write(Paths.get(path), content.getBytes(StandardCharsets.UTF_8));

            // extra options
            // Files.write(Paths.get(path), content.getBytes(), 
			//		StandardOpenOption.CREATE, StandardOpenOption.APPEND);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

} 

输出

c:\projects\app.log

 Hello World 
Java! 

3.Apache commons me(Apache 公用程式)

pom.xml

 <dependency>
		<groupId>commons-io</groupId>
		<artifactId>commons-io</artifactId>
		<version>2.6</version>
	</dependency> 

CommonsIOExample.java

 package com.mkyong;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class CommonsIOExample {

    public static void main(String[] args) {

        String content = "Hello World \r\nJava!\r\n";
        String path = "c:\\projects\\app2.log";

        try {
            FileUtils.writeStringToFile(new File(path), content, StandardCharsets.UTF_8);

            // append
            // FileUtils.writeStringToFile(new File(path), content, StandardCharsets.UTF_8, true);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

} 

4.缓冲写入器

4.1 在过去:

BufferedWriterExample.java

 package com.mkyong;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriterExample {

    public static void main(String[] args) {

        String content = "Hello World \r\nJava!\r\n";
        String path = "c:\\projects\\app.log";

        try (FileWriter writer = new FileWriter(path);
              BufferedWriter bw = new BufferedWriter(writer)) {

            bw.write(content);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

} 

4.2 或者像这样,手动关闭所有资源🙂

BufferedWriterExampleBeforeJava7.java

 package com.mkyong;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriterExampleBeforeJava7 {

    public static void main(String[] args) {

        String content = "Hello World \r\nJava!\r\n";
        String path = "c:\\projects\\app.log";

        BufferedWriter bw = null;
        FileWriter fw = null;

        try {

            fw = new FileWriter(path);
            bw = new BufferedWriter(fw);

            bw.write(content);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bw != null)
                    bw.close();

                if (fw != null)
                    fw.close();

            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

} 

参考

posted @ 2024-11-01 16:32  绝不原创的飞龙  阅读(1)  评论(0编辑  收藏  举报