Mkyong-中文博客翻译-四-
Mkyong 中文博客翻译(四)
原文:Mkyong
Jackson–将 JSON 数组字符串转换为列表
几个 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——如何忽略空字段
在 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
}
参考
杰克逊——如何解析 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-annotations
和jackson-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 包括所有字段,甚至包括static
或transient
字段。
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.常见问题
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
}
}
参考
Jackson–流模型示例
这个 Jackson 教程向你展示了如何使用JsonGenerator
将 JSON 字符串和 JSON 数组写入一个文件,并使用JsonParser
读取它
杰克逊流式 API
JsonGenerator
–编写 JSONJsonParser
–解析 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
参考
- 杰克逊流媒体应用编程接口
- 杰克逊数据绑定
- Jackson–如何解析 JSON
- 杰克逊树模型示例
- Jackson–将 Java 对象转换成 JSON 从 JSON 转换过来
- Gson–如何处理 JSON
杰克逊树模型示例
原文: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
} ]
}
参考
- 使用 Jackson 的 Json 处理:方法#3/3:树遍历
- 杰克逊数据绑定指南
- Jackson 2–将 Java 对象转换成 JSON 从 JSON 转换过来
- stack overflow——使用 Jackson 向 JSON 添加属性
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
并返回一个Integer
、Double
或List
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 这个例子将上面的程序转换成一个方法,该方法接受BiFunction
和Function
作为参数,并将它们链接在一起。
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 是一个函数接口,它接受两个参数并返回一个布尔值,基本上这个BiPredicate
和Predicate
是一样的,但是它需要两个参数进行测试。
@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–流收集器按示例分组
在本文中,我们将向您展示如何使用 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.groupingBy
和Collectors.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]
}
参考
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.toList
将Stream
转换成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–将纪元时间毫秒转换为本地日期或本地日期时间
在 Java 8 中,我们可以使用Instant.ofEpochMilli().atZone()
将以毫秒为单位的纪元时间转换回LocalDate
或LocalDateTime
历元时间至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
获取长值形式的当前历元时间,并将其转换回LocalDate
或LocalDateTime
。
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–将即时转换为时区日期时间
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
参考
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”。
参考
Java 8–将本地日期和本地日期时间转换为日期
一个将 Java 8 java.time.LocalDate
和java.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
参考
- [title =]Java 8–将日期转换为本地日期和本地日期时间](/Java 8/Java-8-Convert-Date-to-local Date-and-local datetime/)
- 本地日期 JavaDoc
- 本地日期时间 JavaDoc
Java 8–将本地日期时间转换为时间戳
在 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.映射到列表
对于简单的Map
到List
的转换,只需使用下面的代码:
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
参考
Java 8–将 ZonedDateTime 转换为时间戳
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–两个本地日期或本地日期时间之间的差异
在 Java 8 中,我们可以用Period
、Duration
或ChronoUnit
来计算两个LocalDate
或LocaldateTime
的差值。
Period
计算两个LocalDate
之差。Duration
计算两个LocalDateTime
之差。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}
参考
Tags : java8 map map filter predicate stream
Java 8–从流中过滤空值
查看包含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());
参考
Java 8 平面图示例
原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-flatmap-example/
本文解释了 Java 8 Stream.flatMap 以及如何使用它。
主题
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。平面图和原始类型
对于原始类型,如int
、long
、double
等。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
参考文献
- Stream.flatMap JavaDoc
- 地图()平面地图()之间的差异
- Java–如何连接数组
- Java 8–如何打印数组
- Java 8–收集器分组和映射示例
- Java 8 Stream.reduce()示例
Java 8 forEach 示例
原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-foreach-examples/
在 Java 8 中,我们可以使用新的forEach
来循环或迭代一个Map
、List
、Set
或Stream
。
主题
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
附注:Set
和Stream
的forEach
工作方式相同。
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
方法,并将其传递给List
和Stream
的forEach
方法。
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 技巧来打印前面带有索引的Array
或List
。
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 本例将Function
与andThen()
链接起来。
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,如何计算斋月日期
斋月是伊斯兰历的第九个月,整月。
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
参考
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–如何计算两个日期之间的天数?
在 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–将流转换为数组
在 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]
参考
Java 8–如何将 IntStream 转换为 int 或 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[]
关键是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–如何格式化本地日期时间
几个例子向你展示如何在 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
参考
Java 8–如何解析带有“DD MMM”(02 Jan)的日期,而不带年份?
这个例子展示了如何解析一个没有指定年份的日期(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/
Java 8 Stream
示例按照键或值对一个Map
进行排序。
1.快速解释
Java 8 中对地图进行排序的步骤。
- 将地图转换成河流
- 分类吧
- 收集并返回新的
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()对列表进行排序
几个例子告诉你如何用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 求和?
在 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 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]
参考
Tags : comparator java8 lambda sorting
Java 8 方法引用,双冒号(::)运算符
在 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)
,其中a
和b
为任意名称,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 方法参考:如何使用
- 了解 Java 8 方法引用
- λ表达式的翻译
- Java 教程–方法参考
- Java 8 教程
- Java 8 函数示例
- Java 8 双功能示例
- Java 8 谓词示例
- Java 8 双预测示例
- Java 8 供应商示例
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
参考
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 可选的优点:
- 不需要空检查。
- 运行时不再出现 NullPointerException。
- 我们可以开发干净整洁的 API。
- 不再有锅炉板代码
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<ScreenResolution> 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<DisplayFeatures> displayFeatures;
// Like wise we can see MemoryFeatures, CameraFeatures etc.
// For simplicity, using only one Features
public Mobile(long id, String brand, String name, Optional<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 Optional<DisplayFeatures> 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)
参考
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/
几个并行执行流的 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()
另一个简单的并行例子是打印a
到z
。对于收藏,我们可以用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–周期和持续时间示例
几个例子向你展示如何使用 Java 8 Duration
、Period
和ChronoUnit
对象找出日期之间的差异。
- 持续时间–以秒和纳秒为单位测量时间。
- 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
参考
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——我们应该在使用后关闭流吗?
只有来源为 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();
}
}
}
参考
Java 8 流–将List<List<String>>
转换为List<String>
如题,我们可以用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()
在 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
参考
Java 8 流——逐行读取文件
在 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()
,它让BufferedReader
以Stream
的形式返回内容。
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();
}
}
}
参考
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
参考
- 还原 JavaDoc
- 二元运算符 JavaDoc
- Java–如何用逗号连接列表字符串
- Java 8–string joiner 示例
Java 8 Stream–peek()不支持 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 流过滤器示例
在本教程中,我们将向您展示几个 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()
过滤一个List
,collect()
将一个流转换成一个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
参考
- Java 8 循环推理在我这里
- Java 8 解释:使用过滤器、映射、流和 Foreach 将 Lambdas 应用于 Java 集合!
- Java 8 forEach 示例
- Java 8 流:多重过滤器与复杂条件
- 用 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'}
]
参考
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.收集器.加入
两个Stream
和Collectors.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;
}
}
参考
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 的提示和例子,希望你喜欢。
常见问题
一些常见问题。
- Java 8 forEach 示例
- Java 8 将列表转换为映射
- Java 8 Lambda:比较器示例
- Java 8 方法引用,双冒号(::)操作符
- Java 8 流过滤器示例
- Java 8 Streams map()示例
1.功能接口
Java 8 引入了@FunctionalInterface
,一个只有一个抽象方法的接口。编译器会将任何满足函数接口的定义的接口视为函数接口;这意味着@FunctionalInterface
注释是可选的。
让我们看看六个基本的功能界面。
连接 | 签名 | 例子 |
---|---|---|
UnaryOperator<T> |
T apply(T t) |
String::toLowerCase ,Math::tan |
BinaryOperator<T> |
T apply(T t1, T t2) |
BigInteger::add ,Math::pow |
Function<T, R> |
R apply(T t) |
Arrays::asList ,Integer::toBinaryString |
Predicate<T, U> |
boolean test(T t, U u) |
String::isEmpty ,Character::isDigit |
Supplier<T> |
T get() |
LocalDate::now ,Instant::now |
Consumer<T> |
void accept(T t) |
System.out::println ,Error::printStackTrace |
- Java 8 函数示例
- Java 8 双功能示例
- Java 8 二元运算符示例
- Java 8 一元运算符示例
- Java 8 谓词示例
- Java 8 双预测示例
- Java 8 消费者示例
- Java 8 双消费示例
- Java 8 供应商示例
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.流
- Java 8 流过滤器示例
- Java 8 Streams map()示例
- Java 8 平面图示例
- Java 8 并行流示例
- Java 8 Stream.iterate 示例
- Java 8 流收集器按示例分组
- Java 8 从流中过滤空值
- Java 8 将流转换为列表
- Java 8 流 findFirst()和 findAny()
- Java 8 Stream.reduce()示例
- Java 8 将流转换为列表
- Java 8 如何用 Stream 对 BigDecimal 求和?
- Java 8 流–逐行读取文件
- Java 8 Stream-Convert List<List
to List - Java 8 Stream–peek()不支持 count()?
- Java 8 使用后应该关闭流吗?
- Java 8 将流转换成数组
- Java 8 如何将 IntStream 转换成整数数组
- Java 8 如何将 IntStream 转换成 int 或 int 数组
- Java 8 如何用 stream.sorted() 对列表进行排序
- Java–如何对所有流整数求和
- Java–如何将原始数组转换为列表
- Java–如何将数组转换成流
- Java–流已经被操作或关闭
4.新日期时间 API
过去,我们使用Date
和Calendar
API 来表示和操作日期。
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
–
示例…
- Java–如何获取当前日期时间
- Java–如何获取当前时间戳
- Java–如何将字符串转换成日期
- Java 8–持续时间和周期示例
- Java 8–如何将字符串转换为本地日期
- Java 8–如何格式化本地日期时间
- Java 8–将 Instant 转换为 LocalDateTime
- Java 8–将 Instant 转换为 ZoneDateTime
- Java 8–将日期转换为本地日期和本地日期时间
- Java 8 – ZonedDateTime examples
- Java–在时区之间转换日期和时间
- Java–如何给当前日期添加天数
- Java 8–temporal adjusts 示例
- Java 8–将纪元时间毫秒转换为本地日期或本地日期时间
- Java 8–两个本地日期或本地日期时间之间的差异
- Java 8–如何计算两个日期之间的天数?
- Java 8–如何解析带有“DD MMM”(02 Jan)的日期,而不带年份?
- Java 8–将本地日期和本地日期时间转换为日期
- Java 8–无法从 TemporalAccessor 获取本地日期时间
- Java 8–将 ZonedDateTime 转换为时间戳
- Java–显示所有 ZoneId 及其 UTC 偏移量
- Java 8–将本地日期时间转换为时间戳
- Java–如何改变字符串中的日期格式
- 检查日期是否超过 6 个月
- Java–如何比较日期
- Java–如何计算运行时间
- Java 8–MinguoDate 示例(台湾日历)
- Java 8–回历,如何计算斋月日期(伊斯兰历)
- Java 日期时间教程
5.Java 8 技巧
- Java 8 可选深度
- Java 8 如何对地图进行排序
- Java 8 将列表转换为映射
- Java 8 过滤一个地图示例
- Java 8 将地图转换为列表
- Java 8 StringJoiner 示例
- Java 8 数学精确例题
- Java 8 forEach print 带索引
- Java 8 将可选的<字符串>转换为字符串
- Java–如何打印金字塔
- Java–检查数组是否包含某个值?
- Java–如何连接数组
- Java–生成一个范围内的随机整数
- Java——如何将一个名字打印 10 次?
- Java–如何在列表中搜索字符串?
- Java–如何从映射中获取键和值
- Java–将文件转换成字符串
- Java–将数组转换成数组列表
- Java–如何检查一个字符串是否为数字
- Java–如何用逗号连接列表字符串
- Java–将逗号分隔的字符串转换成列表
- Java 质数示例
- 如何告诉 Maven 使用 Java 8
- Java . lang . unsupportedclassversionerror
- Java 斐波那契例子
- 如何在 Java 中循环地图
- Java 正则表达式示例
- 如何在 Java 中读取文件–buffered reader
装置
参考
- JDK 最新动态 8
- 为什么我们需要一个新的日期和时间库?
- JSR 310:日期和时间 API
- 流 JavaDoc
Java 8–无法从 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]
参考
- 一元运算符 JavaDoc
- 函数 JavaDoc
- Java 8 函数示例
- Java 8 教程
Java 8 – ZonedDateTime examples
原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java8/java-8-zoneddatetime-examples/
几个例子向你展示如何在不同国家之间转换时区。
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. ## 参考
- 维基百科–夏令时
- DateTimeFormatter JavaDoc
- ZoneddateTime JavaDoc
- 巴黎的时区
- 亚航-航班信息
- Java 8–将 Instant 转换为 ZonedDateTime
- Java–在时区之间转换日期和时间
- Java 8–如何将字符串转换为本地日期
dst java.time java8 timezone utc zoneddatetime zoneoffset
Java 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();
}
}
}
参考
Java–检查数组是否包含某个值?
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.
引用
Java–检查日期是否超过 30 天或 6 个月
本文展示了 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
接口实现的,例如LocalDate
、LocalDateTime
、ZonedDateTime
等。我们可以使用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–将逗号分隔的字符串转换为列表
这个 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
参考
Java–在时区之间转换日期和时间
在本教程中,我们将向您展示几个示例( ZonedDateTime (Java 8) 、 Date 、 Calendar 和 Joda 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
- 如果您使用的是> = 8 的 JDK,请使用新的
java.time.*
框架。 - 如果您使用 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
参考
- 使用 JodaTime 在 Java 中操作日期和时间
- 世界时间服务器
- Java 8 – ZonedDateTime examples
- Java 8–将日期转换为本地日期和本地日期时间
- ZonedDateTime Javadoc
- 日历 JavaDoc
- 日期 JavaDoc
- 简单日期格式 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。参考文献
- Oracle–文档对象模型
- 如何在 Java 中读取 XML 文件—(SAX 解析器)
- 如何在 Java 中读取 XML 文件—(JDOM 解析器)
- JAXB hello world 示例
- 如何在 Java 中读取 XML 文件—(DOM 解析器)
Java 日期和日历示例
本教程向您展示如何使用java.util.Date
和java.util.Calendar
。
1.Java 日期示例
几个使用Date
API 的例子。
示例 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 日历示例
几个使用Calendar
API 的例子。
示例 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);
参考
Java–显示所有 ZoneId 及其 UTC 偏移量
一个 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 示例
使用 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
3。下载源代码
$ git 克隆https://github.com/mkyong/core-java
$ cd java-xml
$ CD src/main/Java/com/mkyong/XML/DOM/XSLT/
4。参考文献
- 维基百科–文档对象模型
- XML 和 XSLT
- 维基百科–XSLT
- Oracle–文档对象模型
- 如何在 Java 中读取 XML 文件—(DOM 解析器)
- 如何用 Java 编写 XML 文件—(DOM 解析器)
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 类型int
和long
不足以存储更大的斐波那契数。下面是寻找第一百万个斐波那契数列的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.
参考
Java 文件.查找示例
原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-files-find-examples/
从 Java 8 开始就有了Files.find
API。它从文件树中快速搜索或查找文件。
主题
在过去,我们总是使用容易出错的递归循环来遍历文件树。这个 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;
}
}
我们还可以使用Files
API 来进一步检查路径。
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.walk
API;它有助于在给定的起始路径遍历文件树。
主题
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——生成一个范围内的随机整数
在本文中,我们将向您展示在一个范围内生成随机整数的三种方法。
- java.util.Random.nextInt
- 数学.随机
- 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
参考
Java——获取正在运行的 JAR 文件的名称或路径
在 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——如何给当前日期添加天数
本文向您展示了如何使用传统的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
参考
Java——如何改变字符串中的日期格式
如果 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
参考
Java——如何检查一个字符串是否是数字
几个 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——如何将原始数组转换成列表
将原始数组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]
参考
Tags : array intstream java8 list primitive stream
Java——如何将数组转换成流
在 Java 8 中,可以使用Arrays.stream
或Stream.of
将数组转换成流。
1.对象数组
对于对象数组,Arrays.stream
和Stream.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.stream
和Stream.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
参考
Java 创建并写入文件
在 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 之前,我们可以使用经典的FileWriter
和BufferedWriter
将文本写入文件。
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.CREATE
和StandardOpenOption.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——如何获取当前日期时间
在本教程中,我们将向您展示如何从新的 Java 8 java.time.*
中获取当前日期时间,如 Localdate 、 LocalTime 、 LocalDateTime 、 ZonedDateTime 、 Instant ,以及旧的日期时间 API,如 Date 和 Calendar 。
目录
- 1。用 Java 获取当前日期时间
- 2 .java.time.LocalDate
- 3。java.time.LocalTime
- 4 .Java . time . localdatetime
- 5. java.time.ZonedDateTime
- 6。java.time.Instant
- 7。java.util.Date(旧版)
- 8。java.util.Calendar(旧版)
- 9。参考文献
摘要
- 对于新的 Java 8
java.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.*
日期时间类,如LocalDate
、LocalDateTime
和ZonedDateTime
。
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。参考文献
- stack overflow-
uuuu
与 Java 中DateTimeFormatter
格式中的yyyy
? - Java 日期时间教程
- 如何在 Java 中获取当前时间戳
- 维基百科–纪元时间
- 局部日期
- 当地时间
- 局部日期时间
- ZonedDateTime
- 瞬间
- 日期
- 日历
- DateTimeFormatter
- 简单日期格式
Java——如何从 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?
换行符,也称为行尾(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 数组的方法。
- Apache Commons Lang–ArrayUtils
- Java API
- 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 流例子吗?请在下面评论。
参考
Tags : array java java8 stream
Java–如何用逗号连接列表字符串
在 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
参考
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.nCopies
和String.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.fill
和String.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
*********
*******
*****
***
*
参考
如何用 Java 读取文件
原文:http://web.archive.org/web/20230101150211/https://mkyong.com/java/java-how-to-read-a-file/
本文重点介绍几种在 Java 中读取文件的常用方法。
Files.lines
,返回一个Stream
(Java 8)Files.readString
,返回一个String
(Java 11),最大文件大小 2G。Files.readAllBytes
,返回一个byte[]
(Java 7),最大文件大小 2G。Files.readAllLines
,返回一个List<String>
(Java 8)BufferedReader
,经典老朋友(Java 1.1 - >永远)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.newStringNoRepl
将byte[]
转换回一个字符串。
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
参考
- 文件 JavaDocs
- BufferedReader JavaDocs
- 扫描仪 JavaDocs
- Java 教程——阅读、编写和创建文件
- 如何在 Java 中读取文件–buffered reader
- Java–从资源文件夹中读取文件
Java——如何将字符串保存到文件中
在 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();
}
}
}
}