“ Java ยังไม่ตายและผู้คนเริ่มคิดออก”
บทช่วยสอนนี้จะใช้รหัสคำอธิบายประกอบอย่างง่ายเพื่ออธิบายคุณสมบัติใหม่และคุณจะไม่เห็นข้อความบล็อกบัสเตอร์
1. วิธีเริ่มต้นของอินเตอร์เฟส
Java 8 ช่วยให้เราสามารถเพิ่มการใช้วิธีการที่ไม่ได้ใช้กับอินเทอร์เฟซเพียงใช้คำหลักเริ่มต้น
การคัดลอกรหัสมีดังนี้:
สูตรอินเตอร์เฟส {
คำนวณสองเท่า (int a);
SQRT double double (int a) {
return math.sqrt (a);
-
-
นอกเหนือจากการมีวิธีการคำนวณอินเทอร์เฟซสูตรยังกำหนดวิธี SQRT
การคัดลอกรหัสมีดังนี้:
สูตรสูตร = สูตรใหม่ () {
@Override
การคำนวณสองครั้งสาธารณะ (int a) {
ส่งคืน SQRT (A * 100);
-
-
Formula.calment (100);
Formula.sqrt (16);
สูตรในบทความถูกนำมาใช้เป็นอินสแตนซ์ของคลาสที่ไม่ระบุชื่อ ในส่วนถัดไปเราจะเห็นวิธีที่ง่ายกว่าในการใช้อินเตอร์เฟสวิธีการเดียว
หมายเหตุของนักแปล: มีเพียงมรดกเดียวใน Java ในภาษาอื่นวิธีการมีคลาสมีรหัสที่นำกลับมาใช้ใหม่ได้ในเวลาเดียวกันเรียกว่า Mixin Java 8 พิเศษใหม่นี้ใกล้เคียงกับลักษณะของ Scala จากมุมมองของการใช้งานคอมไพเลอร์ นอกจากนี้ยังมีแนวคิดที่เรียกว่าวิธีการขยายใน C#ซึ่งอนุญาตให้ขยายประเภทที่มีอยู่ซึ่งแตกต่างกันไปตามความหมายใน Java 8
2. การแสดงออกของแลมบ์ดา
ก่อนอื่นมาดูกันว่าการจัดเรียงสตริงใน Java รุ่นเก่า:
การคัดลอกรหัสมีดังนี้:
รายการ <String> names = array.aslist ("Peter", "Anna", "Mike", "Xenia");
collections.sort (ชื่อ, ตัวเปรียบเทียบใหม่ <string> () {
@Override
INT Public Compare (String A, String B) {
กลับ B.Compareto (a);
-
-
เพียงผ่านวัตถุรายการและตัวเปรียบเทียบกับคอลเลกชันแบบคงที่ sort เพื่อจัดเรียงตามลำดับที่ระบุ มันมักจะทำเพื่อสร้างวัตถุเปรียบเทียบที่ไม่ระบุชื่อและส่งผ่านไปยังวิธีการเรียงลำดับ
ใน Java 8 คุณไม่จำเป็นต้องใช้วิธีการดั้งเดิมของวัตถุที่ไม่ระบุชื่อ
การคัดลอกรหัสมีดังนี้:
collections.sort (ชื่อ, (String A, String B) -> {
กลับ B.Compareto (a);
-
ดูสิรหัสจะแบ่งส่วนและอ่านได้มากขึ้น แต่สามารถเขียนสั้น ๆ ได้จริง:
การคัดลอกรหัสมีดังนี้:
collections.sort (ชื่อ, (String A, String B) -> B.Compareto (A));
สำหรับฟังก์ชั่นร่างกายที่มีรหัสเพียงบรรทัดเดียวคุณสามารถลบวงเล็บปีกกา {} และส่งคืนคำหลักได้ แต่คุณสามารถเขียนสั้นลงได้:
การคัดลอกรหัสมีดังนี้:
collections.sort (ชื่อ, (a, b) -> b.compareto (a));
คอมไพเลอร์ Java สามารถอนุมานประเภทพารามิเตอร์โดยอัตโนมัติได้ดังนั้นคุณไม่ต้องเขียนประเภทอีกครั้ง ถัดไปมาดูกันว่าการแสดงออกของแลมบ์ดาที่สะดวกกว่านี้สามารถทำได้:
3. อินเทอร์เฟซที่ใช้งานได้
Lambda Expressions แสดงในระบบประเภทของ Java ได้อย่างไร? นิพจน์แลมบ์ดาแต่ละชนิดสอดคล้องกับประเภทมักจะเป็นประเภทอินเตอร์เฟส "อินเทอร์เฟซฟังก์ชัน" หมายถึงอินเทอร์เฟซที่มีเฉพาะวิธีนามธรรมและการแสดงออกของแลมบ์ดาแต่ละประเภทของประเภทนี้จะถูกจับคู่กับวิธีนามธรรมนี้ เนื่องจากวิธีการเริ่มต้นไม่ใช่วิธีนามธรรมคุณยังสามารถเพิ่มวิธีการเริ่มต้นในอินเตอร์เฟสการทำงานของคุณ
เราสามารถรักษานิพจน์แลมบ์ดาเป็นประเภทอินเทอร์เฟซใด ๆ ที่มีเพียงวิธีเดียวที่เป็นนามธรรมเพื่อให้แน่ใจว่าอินเทอร์เฟซของคุณจะต้องปฏิบัติตามข้อกำหนดนี้ คำอธิบายประกอบคอมไพเลอร์จะพบว่าอินเทอร์เฟซที่คุณทำเครื่องหมายนั้นมีคำอธิบายประกอบโดยคำอธิบายประกอบนี้จะมีข้อผิดพลาดเมื่อมีวิธีนามธรรมมากกว่าหนึ่งวิธี
ตัวอย่างมีดังนี้:
การคัดลอกรหัสมีดังนี้:
@functionalInterface
ตัวแปลงอินเตอร์เฟส <f, t> {
t แปลง (f จาก);
-
Converter <String, Integer> Converter = (จาก) -> Integer.ValueOf (จาก);
Integer Converted = Converter.Convert ("123");
System.out.println (แปลง);
ควรสังเกตว่าหากไม่ได้ระบุ @functionalInterface รหัสด้านบนจะถูกต้องเช่นกัน
หมายเหตุบันทึกของนักแปล Lambda Expressions ไปยังอินเทอร์เฟซวิธีเดียว ฟังก์ชั่น
4. วิธีการและการอ้างอิงตัวสร้าง
รหัสในส่วนก่อนหน้านี้ยังสามารถแสดงโดยการอ้างอิงวิธีการคงที่:
การคัดลอกรหัสมีดังนี้:
Converter <String, Integer> Converter = Integer :: Valueof;
Integer Converted = Converter.Convert ("123");
System.out.println (แปลง);
Java 8 ช่วยให้คุณใช้คำหลัก: การอ้างอิงวิธีการหรือการอ้างอิง
การคัดลอกรหัสมีดังนี้:
ตัวแปลง = บางสิ่งบางอย่าง :: startswith;
สตริงแปลง = converter.convert ("java");
System.out.println (แปลง);
มาดูกันว่าผู้สร้างมีการอ้างอิงโดยใช้คำหลัก: ก่อน
การคัดลอกรหัสมีดังนี้:
คนในชั้นเรียน {
String FirstName;
สตริงนามสกุล;
บุคคล() {}
Person (String FirstName, String LastName) {
this.firstName = FirstName;
this.lastName = LastName;
-
-
ต่อไปเราระบุอินเทอร์เฟซ Object Factory เพื่อสร้างวัตถุบุคคล:
การคัดลอกรหัสมีดังนี้:
อินเตอร์เฟส personfactory <p ขยายบุคคล> {
p สร้าง (สตริง firstName, String LastName);
-
ที่นี่เราใช้การอ้างอิงตัวสร้างเพื่อเชื่อมโยงพวกเขาแทนที่จะใช้โรงงานที่สมบูรณ์:
การคัดลอกรหัสมีดังนี้:
personfactory <person> personfactory = บุคคล :: ใหม่;
บุคคลบุคคล = personfactory.create ("Peter", "Parker");
เราจำเป็นต้องใช้บุคคล :: ใหม่เพื่อรับการอ้างอิงถึงตัวสร้างคลาสบุคคล
5. ขอบเขตแลมบ์ดา
วิธีการเข้าถึงขอบเขตภายนอกในนิพจน์แลมบ์ดานั้นคล้ายกับในวัตถุที่ไม่ระบุชื่อรุ่นเก่า คุณสามารถเข้าถึงตัวแปรท้องถิ่นภายนอกที่ทำเครื่องหมายสุดท้ายหรือฟิลด์และตัวแปรคงที่ของอินสแตนซ์
6. เข้าถึงตัวแปรท้องถิ่น
เราสามารถเข้าถึงตัวแปรท้องถิ่นภายนอกโดยตรงในนิพจน์แลมบ์ดา:
การคัดลอกรหัสมีดังนี้:
int สุดท้าย num = 1;
ตัวแปลง <จำนวนเต็ม, สตริง> stringconverter =
(จาก) -> string.valueof (จาก + num);
StringConverter.Convert (2);
แต่แตกต่างจากวัตถุที่ไม่ระบุชื่อตัวแปร NUM ที่นี่สามารถประกาศได้ว่าเป็นขั้นสุดท้ายโดยไม่ต้องประกาศว่าเป็นขั้นสุดท้ายและรหัสก็ถูกต้องเช่นกัน:
การคัดลอกรหัสมีดังนี้:
int num = 1;
ตัวแปลง <จำนวนเต็ม, สตริง> stringconverter =
(จาก) -> string.valueof (จาก + num);
StringConverter.Convert (2);
อย่างไรก็ตาม NUM ที่นี่จะต้องไม่ได้รับการแก้ไขโดยรหัสที่ตามมา (นั่นคือโดยปริยายมีความหมายสุดท้าย) ตัวอย่างเช่นไม่สามารถรวบรวมต่อไปนี้:
การคัดลอกรหัสมีดังนี้:
int num = 1;
ตัวแปลง <จำนวนเต็ม, สตริง> stringconverter =
(จาก) -> string.valueof (จาก + num);
num = 3;
ไม่อนุญาตให้พยายามปรับเปลี่ยน NUM ในนิพจน์แลมบ์ดา
7. การเข้าถึงฟิลด์วัตถุวัตถุและตัวแปรคงที่
ซึ่งแตกต่างจากตัวแปรท้องถิ่นฟิลด์และตัวแปรคงที่ภายในแลมบ์ดาสามารถอ่านและเขียนได้ พฤติกรรมนี้สอดคล้องกับวัตถุที่ไม่ระบุชื่อ:
คัดลอกรหัสดังนี้: คลาส Lambda4 {
คงที่ int outerstaticnum;
int outernum;
เป็นโมฆะ testscopes () {
ตัวแปลง <จำนวนเต็ม, สตริง> stringconverter1 = (จาก) -> {
outernum = 23;
return string.valueof (จาก);
-
ตัวแปลง <จำนวนเต็ม, สตริง> stringconverter2 = (จาก) -> {
outerstaticNum = 72;
return string.valueof (จาก);
-
-
-
8. วิธีเริ่มต้นในการเข้าถึงอินเทอร์เฟซ
โปรดจำไว้ว่าตัวอย่างสูตรในส่วนแรก
วิธีการเริ่มต้นไม่สามารถเข้าถึงได้ในนิพจน์แลมบ์ดาและรหัสต่อไปนี้จะไม่ถูกรวบรวม:
การคัดลอกรหัสมีดังนี้:
สูตรสูตร = (a) -> sqrt (a * 100);
อินเทอร์เฟซการใช้งานในตัว
JDK 1.8 API มีอินเทอร์เฟซที่ใช้งานได้หลายอย่างเช่นตัวเปรียบเทียบหรืออินเทอร์เฟซที่ใช้งานได้ทั่วไปที่ใช้ใน Java เก่าและอินเทอร์เฟซเหล่านี้ได้เพิ่มคำอธิบายประกอบ @functionalInterface เพื่อใช้กับ Lambdas
Java 8 API ยังมีอินเทอร์เฟซที่ใช้งานได้ใหม่มากมายเพื่อให้การทำงานสะดวกขึ้น
อินเทอร์เฟซ
อินเทอร์เฟซเพรดิเคตมีพารามิเตอร์เดียวเท่านั้นซึ่งส่งคืนประเภทบูลีน อินเทอร์เฟซนี้มีจำนวนวิธีเริ่มต้นเพื่อรวมเพรดิเคตเข้ากับ logics ที่ซับซ้อนอื่น ๆ (เช่น: กับหรือไม่ใช่):
การคัดลอกรหัสมีดังนี้:
Predicate <String> Predicate = (S) -> S.Length ()> 0;
Predict.test ("foo");
Predict.negate (). ทดสอบ ("foo");
เพรดิเคต <boolean> nonnull = objects :: nonnull;
เพรดิเคต <บูลีน> isnull = วัตถุ :: isnull;
Predicate <String> isempty = string :: isempty;
Predicate <String> isNotEmpty = isEmpty.negate ();
อินเตอร์เฟสฟังก์ชั่น
อินเทอร์เฟซฟังก์ชั่นมีพารามิเตอร์และส่งคืนผลลัพธ์และมาพร้อมกับวิธีการเริ่มต้นบางอย่าง (เขียนและจากนั้น) ที่สามารถรวมกับฟังก์ชั่นอื่น ๆ :
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น <สตริง, จำนวนเต็ม> tointeger = จำนวนเต็ม :: valueof;
ฟังก์ชั่น <สตริงสตริง> backtoString = toInteger.andthen (สตริง :: valueof);
backtostring.apply ("123");
อินเทอร์เฟซซัพพลายเออร์
อินเทอร์เฟซซัพพลายเออร์ส่งคืนค่าประเภทใดก็ได้
การคัดลอกรหัสมีดังนี้:
ซัพพลายเออร์ <Person> PERSONSUPPLIER = บุคคล :: ใหม่;
PersonSupplier.get ();
อินเทอร์เฟซผู้บริโภค
อินเทอร์เฟซผู้บริโภคแสดงถึงการดำเนินการที่ดำเนินการกับพารามิเตอร์เดียว
การคัดลอกรหัสมีดังนี้:
ผู้บริโภค <Person> greeter = (p) -> system.out.println ("สวัสดี," + p.firstname);
greeter.accept (คนใหม่ ("ลุค", "Skywalker"));
อินเตอร์เฟสเปรียบเทียบ
ตัวเปรียบเทียบเป็นอินเทอร์เฟซคลาสสิกใน Java เก่าและ Java 8 ได้เพิ่มวิธีการเริ่มต้นที่หลากหลาย:
การคัดลอกรหัสมีดังนี้:
ตัวเปรียบเทียบ <person> comparator = (p1, p2) -> p1.firstname.compareto (p2.firstname);
บุคคล p1 = บุคคลใหม่ ("จอห์น", "doe");
Person P2 = บุคคลใหม่ ("Alice", "Wonderland");
comparator.compare (p1, p2);
comparator.reversed (). เปรียบเทียบ (p1, p2);
อินเทอร์เฟซเสริม
ตัวเลือกไม่ใช่ฟังก์ชั่น แต่เป็นอินเทอร์เฟซ
ตัวเลือกถูกกำหนดให้เป็นคอนเทนเนอร์อย่างง่ายที่มีค่าอาจเป็นโมฆะหรือไม่ ก่อนที่ Java 8 ฟังก์ชั่นควรส่งคืนวัตถุที่ไม่ว่างเปล่า แต่บางครั้งมันอาจส่งคืน Null
การคัดลอกรหัสมีดังนี้:
ตัวเลือก <String> ตัวเลือก = ไม่เป็นตัวเลือกของ ("BAM");
ตัวเลือก. ispresent ();
ไม่บังคับ. get ();
ตัวเลือก. orelse ("ทางเลือก");
ตัวเลือก. ifpresent ((s) -> system.out.println (S.Charat (0));
สตรีมอินเทอร์เฟซ
java.util.stream แสดงลำดับของการดำเนินการที่สามารถนำไปใช้กับชุดขององค์ประกอบในครั้งเดียว การดำเนินการสตรีมแบ่งออกเป็นสองประเภท: การดำเนินการระดับกลางหรือการดำเนินการขั้นสุดท้าย การสร้างสตรีมจำเป็นต้องมีการระบุแหล่งข้อมูลเช่นคลาสย่อยของ java.util.collection รายการหรือชุดซึ่งไม่ได้รับการสนับสนุนด้วยแผนที่ การดำเนินการสตรีมสามารถดำเนินการตามลำดับหรือขนานกัน
ก่อนอื่นมาดูกันว่าการใช้สตรีมเป็นอย่างไร
การคัดลอกรหัสมีดังนี้:
รายการ <String> stringCollection = new ArrayList <> ();
StringCollection.add ("DDD2");
StringCollection.add ("AAA2");
StringCollection.add ("BBB1");
StringCollection.add ("AAA1");
StringCollection.add ("BBB3");
StringCollection.add ("CCC");
StringCollection.add ("BBB2");
StringCollection.add ("DDD1");
Java 8 ขยายคลาสคอลเลกชันและสามารถสร้างสตรีมผ่าน collection.stream () หรือ collection.parallelsstream () ส่วนต่อไปนี้จะอธิบายการดำเนินการสตรีมที่ใช้กันทั่วไปโดยละเอียด:
ตัวกรองตัวกรอง
การกรองจะถูกกรองผ่านอินเทอร์เฟซเพรดิเคตและองค์ประกอบที่ตรงตามเกณฑ์เท่านั้น Foreach ต้องการฟังก์ชั่นในการเรียกใช้องค์ประกอบที่กรองตามลำดับ Foreach เป็นการดำเนินการขั้นสุดท้ายดังนั้นเราจึงไม่สามารถดำเนินการสตรีมอื่น ๆ หลังจาก foreach
การคัดลอกรหัสมีดังนี้:
การรวบรวมสตริง
.ลำธาร()
.filter ((s) -> s.startswith ("a")))
. foreach (system.out :: println);
// "AAA2", "AAA1"
เรียงลำดับ
การเรียงลำดับคือการดำเนินการระดับกลางและสตรีมที่ส่งคืนหลังจากการเรียงลำดับจะถูกส่งคืน หากคุณไม่ได้ระบุตัวเปรียบเทียบแบบกำหนดเองการเรียงลำดับเริ่มต้นจะถูกใช้
การคัดลอกรหัสมีดังนี้:
การรวบรวมสตริง
.ลำธาร()
.Stort ()
.filter ((s) -> s.startswith ("a")))
. foreach (system.out :: println);
// "AAA1", "AAA2"
ควรสังเกตว่าการเรียงลำดับจะสร้างสตรีมที่จัดเรียงเท่านั้นและจะไม่ส่งผลกระทบต่อแหล่งข้อมูลดั้งเดิม
การคัดลอกรหัสมีดังนี้:
System.out.println (StringCollection);
// DDD2, AAA2, BBB1, AAA1, BBB3, CCC, BBB2, DDD1
แผนที่แผนที่
แผนที่การทำงานระดับกลางแปลงองค์ประกอบเป็นวัตถุเพิ่มเติมตามลำดับตามอินเตอร์เฟสฟังก์ชั่นที่ระบุ คุณยังสามารถใช้แผนที่เพื่อแปลงวัตถุเป็นประเภทอื่น ๆ
การคัดลอกรหัสมีดังนี้:
การรวบรวมสตริง
.ลำธาร()
.map (String :: Touppercase)
.Stort ((a, b) -> b.Compareto (a))
. foreach (system.out :: println);
// "DDD2", "DDD1", "CCC", "BBB3", "BBB2", "AAA2", "AAA1"
จับคู่
สตรีมให้การดำเนินการที่ตรงกันที่หลากหลายช่วยให้สามารถตรวจจับได้ว่าภาคแสดงที่ระบุตรงกับสตรีมทั้งหมดหรือไม่ การดำเนินการที่ตรงกันทั้งหมดเป็นการดำเนินการขั้นสุดท้ายและส่งคืนค่าบูลีนประเภท
การคัดลอกรหัสมีดังนี้:
บูลีน anystartswitha =
การรวบรวมสตริง
.ลำธาร()
.anymatch ((s) -> s.startswith ("a"));
System.out.println (Anystartswitha);
บูลีน AllStartSwitha =
การรวบรวมสตริง
.ลำธาร()
.AllMatch ((S) -> S.Startswith ("A"));
System.out.println (Allstartswitha);
บูลีน nonstartswithz =
การรวบรวมสตริง
.ลำธาร()
.Nonematch ((s) -> s.startswith ("z"));
System.out.println (NonesTartswithz);
นับ
การนับเป็นการดำเนินการขั้นสุดท้ายซึ่งส่งคืนจำนวนองค์ประกอบในสตรีมและประเภทค่าส่งคืนนั้นยาว
การคัดลอกรหัสมีดังนี้:
Long StartSwithB =
การรวบรวมสตริง
.ลำธาร()
.filter ((S) -> S.Startswith ("B")))
.นับ();
System.out.println (startswithb);
ลดกฎระเบียบ
นี่คือการดำเนินการขั้นสุดท้ายทำให้มีหลายองค์ประกอบในสตรีมที่กำหนดเป็นองค์ประกอบหนึ่งผ่านฟังก์ชั่นที่ระบุและผลลัพธ์ของการมีสิทธิ์ถูกแสดงโดยอินเทอร์เฟซเสริม:
การคัดลอกรหัสมีดังนี้:
ตัวเลือก <String> ลดลง =
การรวบรวมสตริง
.ลำธาร()
.Stort ()
.Reduce ((S1, S2) -> S1 + "#" + S2);
ลดลงไป (System.out :: println);
// "aaa1#aaa2#bb1#bb2#bb3#ccc#ddd1#ddd2"
สตรีมแบบขนาน
ดังที่ได้กล่าวไว้ก่อนหน้านี้สตรีมมีสองประเภท: อนุกรมและขนาน
ตัวอย่างต่อไปนี้แสดงวิธีปรับปรุงประสิทธิภาพผ่านสตรีมแบบขนาน:
ก่อนอื่นเราสร้างตารางขนาดใหญ่โดยไม่มีองค์ประกอบที่ซ้ำกัน:
การคัดลอกรหัสมีดังนี้:
int max = 1000000;
รายการ <String> values = arrayList ใหม่ <> (สูงสุด);
สำหรับ (int i = 0; i <max; i ++) {
uuid uuid = uuid.randomuuid ();
value.add (uuid.toString ());
-
จากนั้นเราจะคำนวณระยะเวลาในการเรียงลำดับสตรีมนี้
เรียงลำดับแบบอนุกรม:
การคัดลอกรหัสมีดังนี้:
t0 long = system.nanotime ();
long count = values.stream (). เรียงลำดับ (). count ();
System.out.println (นับ);
t1 ยาว = system.nanotime ();
Long Millis = TimeUnit.nanoseconds.tomillis (T1 - T0);
System.out.println (string.format ("เรียงลำดับเรียงลำดับใช้: %d ms", millis));
// เวลาอนุกรม: 899 ms
การเรียงลำดับแบบขนาน:
การคัดลอกรหัสมีดังนี้:
t0 long = system.nanotime ();
long count = values.parallelStream (). เรียงลำดับ (). count ();
System.out.println (นับ);
t1 ยาว = system.nanotime ();
Long Millis = TimeUnit.nanoseconds.tomillis (T1 - T0);
System.out.println (string.format ("การเรียงลำดับแบบขนานใช้: %d ms", millis));
// การเรียงลำดับแบบขนานต้องใช้เวลา: 472 ms
สองรหัสข้างต้นเกือบจะเหมือนกัน แต่เวอร์ชันคู่ขนานนั้นเร็วถึง 50%
แผนที่
ดังที่ได้กล่าวไว้ก่อนหน้านี้ประเภทแผนที่ไม่รองรับสตรีม แต่แผนที่มีวิธีการใหม่และมีประโยชน์ในการจัดการงานประจำวัน
การคัดลอกรหัสมีดังนี้:
แผนที่ <จำนวนเต็ม, สตริง> map = new hashmap <> ();
สำหรับ (int i = 0; i <10; i ++) {
map.putifabsent (i, "val" + i);
-
map.foreach ((id, val) -> system.out.println (val));
รหัสข้างต้นเข้าใจง่าย
ตัวอย่างต่อไปนี้แสดงฟังก์ชั่นที่มีประโยชน์อื่น ๆ บนแผนที่:
การคัดลอกรหัสมีดังนี้:
map.computeifpresent (3, (num, val) -> val + num);
map.get (3);
map.computeifpresent (9, (num, val) -> null);
map.containskey (9);
map.computeifabsent (23, num -> "val" + num);
map.containskey (23);
map.computeifabsent (3, num -> "bam");
map.get (3);
ถัดไปแสดงวิธีการลบรายการในแผนที่ที่ตรงกับปุ่มทั้งหมด:
การคัดลอกรหัสมีดังนี้:
MAP.REMOVE (3, "Val3");
map.get (3);
map.remove (3, "val33");
map.get (3);
วิธีที่มีประโยชน์อีกวิธีหนึ่ง:
การคัดลอกรหัสมีดังนี้:
map.getordefault (42, "ไม่พบ");
นอกจากนี้ยังง่ายต่อการรวมองค์ประกอบของแผนที่:
การคัดลอกรหัสมีดังนี้:
map.merge (9, "val9", (ค่า, newValue) -> value.concat (newValue));
map.get (9);
map.merge (9, "concat", (value, newValue) -> value.concat (newValue));
map.get (9);
สิ่งที่ผสานคือแทรกหากไม่มีชื่อคีย์มิฉะนั้นจะรวมค่าที่สอดคล้องกับคีย์ดั้งเดิมและใส่เข้าไปในแผนที่
9. วันที่ API
Java 8 มีชุดเวลาและวันที่ใหม่ล่าสุดภายใต้แพ็คเกจ java.time API วันที่ใหม่นั้นคล้ายกับห้องสมุดโอเพนซอร์ส Joda-Time แต่ไม่เหมือนกัน
นาฬิกานาฬิกา
คลาสนาฬิกามีวิธีการเข้าถึงวันที่และเวลาปัจจุบัน จุดที่เฉพาะเจาะจงในเวลายังสามารถแสดงด้วยคลาสทันทีซึ่งสามารถใช้ในการสร้างวัตถุ Java.util.date เก่า
การคัดลอกรหัสมีดังนี้:
นาฬิกา = นาฬิกา SystemDefaultZone ();
มิลลิสยาว = นาฬิกา millis ();
ทันที = นาฬิกาทันที ();
วันที่ legacydate = วันที่ (ทันที);
เขตเวลาเขตเวลา
ใน API ใหม่โซนเวลาจะแสดงโดย ZoneID โซนเวลาสามารถหาได้ง่ายโดยใช้วิธีการคงที่ของ โซนเวลากำหนดความแตกต่างของเวลาเป็นเวลา UTS ซึ่งมีความสำคัญอย่างยิ่งเมื่อแปลงระหว่างวัตถุจุดเวลาทันทีและวัตถุวันที่ท้องถิ่น
การคัดลอกรหัสมีดังนี้:
System.out.println (zoneid.getavailableablezoneids ());
// พิมพ์รหัสเวลาที่มีอยู่ทั้งหมด
ZONEID ZONE1 = ZONEID.OF ("ยุโรป/เบอร์ลิน");
ZONEID ZONE2 = ZONEID.OF ("บราซิล/ตะวันออก");
System.out.println (zone1.getRules ());
System.out.println (zone2.getRules ());
// zonerules [currentstandardoffset =+01: 00]
// zonerules [currentstandardoffset = -03: 00]
เวลาท้องถิ่นในท้องถิ่น
LocalTime กำหนดเวลาที่ไม่มีข้อมูลโซนเวลาเช่น 22.00 น. หรือ 17:30:15 น. ตัวอย่างต่อไปนี้สร้างสองครั้งในท้องถิ่นโดยใช้โซนเวลาที่สร้างขึ้นโดยรหัสก่อนหน้า เวลาจะถูกเปรียบเทียบและความแตกต่างของเวลาระหว่างสองครั้งจะคำนวณเป็นชั่วโมงและนาที:
การคัดลอกรหัสมีดังนี้:
localtime now1 = localtime.now (zone1);
localtime now2 = localtime.now (zone2);
System.out.println (Now1.isbefore (Now2));
ชั่วโมงยาวระหว่าง = Chronounit.hours.weetween (Now1, Now2);
Long Minutebeween = Chronounit.minutes.weetween (Now1, Now2);
System.out.println (ชั่วโมงระหว่าง);
System.out.println (นาทีระหว่าง);
LocalTime มีวิธีการที่หลากหลายของโรงงานเพื่อทำให้การสร้างวัตถุง่ายขึ้นรวมถึงสตริงเวลาการแยกวิเคราะห์
การคัดลอกรหัสมีดังนี้:
LocalTime late = localtime.of (23, 59, 59);
System.out.println (สาย);
Datetimeformatter Germanformatter =
Datetimeformatter
.oflocalizedTime (formatStyle.SHORT)
.WithLocale (locale.german);
LocalTime leettime = localtime.parse ("13:37", Germanformatter);
System.out.println (leettime);
วันที่ท้องถิ่น
LocalDate แสดงถึงวันที่ที่แน่นอนเช่น 2014-03-11 ค่าของวัตถุนี้ไม่เปลี่ยนรูปและโดยทั่วไปเหมือนกับของ LocalTime ตัวอย่างต่อไปนี้แสดงวิธีเพิ่ม/ดวงจันทร์/ปีไปยังวัตถุวันที่ โปรดทราบว่าวัตถุเหล่านี้ไม่เปลี่ยนรูปและการดำเนินการส่งคืนอินสแตนซ์ใหม่
การคัดลอกรหัสมีดังนี้:
localDate วันนี้ = localDate.now ();
localDate พรุ่งนี้ = วันนี้ plus (1, chronounit.days);
LocalDate เมื่อวาน = พรุ่งนี้วัน (2);
LocalDate IndependenceDay = localDate.OF (2014, เดือนกรกฎาคม, 4);
dayofweek dayofweek = Independenceday.getdayofweek ();
System.out.println (Dayofweek);
การแยกวิเคราะห์ประเภท localdate จากสตริงนั้นง่ายพอ ๆ กับการแยกวิเคราะห์ LocalTime:
การคัดลอกรหัสมีดังนี้:
Datetimeformatter Germanformatter =
Datetimeformatter
.oflocalizedDate (FormatStyle.Medium)
.WithLocale (locale.german);
localdate xmas = localdate.parse ("24.12.2014", Germanformatter);
System.out.println (xmas);
localDateTime local DateTime
LocalDateTime แสดงถึงทั้งเวลาและวันที่ซึ่งเทียบเท่ากับการรวมของเนื้อหาของสองส่วนแรกเป็นหนึ่งวัตถุ LocalDatetime เช่น LocalTime และ LocalDate นั้นไม่เปลี่ยนรูป LocalDatetime มีวิธีการบางอย่างในการเข้าถึงฟิลด์เฉพาะ
การคัดลอกรหัสมีดังนี้:
LocalDatetime Sylvester = LocalDateTime.OF (2014, เดือนธันวาคม, 31, 23, 59, 59);
dayofweek dayofweek = sylvester.getdayofweek ();
System.out.println (Dayofweek);
เดือนเดือน = sylvester.getMonth ();
System.out.println (เดือน);
Long Minuteofday = sylvester.getLong (Chronofield.minute_of_day);
System.out.println (นาที);
เพียงแค่แนบข้อมูลโซนเวลาและสามารถแปลงเป็นวัตถุทันทีที่เกิดขึ้นได้
การคัดลอกรหัสมีดังนี้:
ทันที = ซิลเวสเตอร์
.atzone (ZoneID.SystemDefault ())
.toinstant ();
วันที่ legacydate = วันที่ (ทันที);
System.out.println (Legacydate);
การจัดรูปแบบ localDatetime นั้นเหมือนกับเวลาในการจัดรูปแบบและวันที่
การคัดลอกรหัสมีดังนี้:
datetimeformatter formatter =
Datetimeformatter
.ofpattern ("MMM DD, YYYY - HH: MM");
LocalDateTime parsed = localDateTime.parse ("พ.ย. 03, 2014 - 07:13", Formatter);
สตริงสตริง = formatter.format (แยกวิเคราะห์);
System.out.println (String);
ซึ่งแตกต่างจาก java.text.numberFormat เวอร์ชันใหม่ของ DateTimeFormatter ไม่เปลี่ยนรูปดังนั้นจึงเป็นเธรดที่ปลอดภัย
ข้อมูลโดยละเอียดเกี่ยวกับรูปแบบเวลาและวันที่: http://download.java.net/jdk8/docs/api/java/time/format/datetimeformatter.html
10. หมายเหตุหมายเหตุประกอบ
มีการรองรับคำอธิบายประกอบหลายรายการใน Java 8 ก่อนอื่นให้ดูตัวอย่างเพื่อทำความเข้าใจว่ามันหมายถึงอะไร
ขั้นแรกให้กำหนดคำใบ้คำแนะนำที่บรรจุไว้เพื่อวางชุดคำใบ้คำใบ้เฉพาะ:
การคัดลอกรหัสมีดังนี้:
@Interface คำแนะนำ {
คำใบ้ [] ค่า ();
-
@Repeatable (คำแนะนำ)
@Interface คำใบ้ {
ค่าสตริง ();
-
Java 8 ช่วยให้เราสามารถใช้คำอธิบายประกอบของประเภทเดียวกันหลาย ๆ ครั้งเพียงแค่ติดฉลากคำอธิบายประกอบ @repeatable
ตัวอย่างที่ 1: ใช้คลาส wrapper เป็นคอนเทนเนอร์เพื่อจัดเก็บคำอธิบายประกอบหลายรายการ (วิธีเก่า)
การคัดลอกรหัสมีดังนี้:
@hints ({ @hint ("hint1"), @hint ("hint2")})
บุคคลในชั้นเรียน {}
ตัวอย่างที่ 2: การใช้คำอธิบายประกอบหลายรายการ (วิธีใหม่)
การคัดลอกรหัสมีดังนี้:
@hint ("Hint1")
@hint ("Hint2")
บุคคลในชั้นเรียน {}
ในตัวอย่างที่สองคอมไพเลอร์ Java จะกำหนดคำอธิบายประกอบ @hints สำหรับคุณโดยปริยาย
การคัดลอกรหัสมีดังนี้:
คำใบ้ = person.class.getannotation (Hint.class);
System.out.println (คำใบ้);
คำแนะนำคำแนะนำ 1 = person.class.getannotation (คำแนะนำ);
System.out.println (Hints1.value (). ความยาว);
คำใบ้ [] HINTS2 = person.class.getAnnotationsByType (Hint.class);
System.out.println (Hints2.length);
แม้ว่าเราจะไม่ได้กำหนดคำอธิบายประกอบ @hints ในชั้นเรียนบุคคลเรายังสามารถรับคำอธิบายประกอบ @hints ผ่าน getannotation (คำแนะนำ)
นอกจากนี้ยังมีการเพิ่มคำอธิบายประกอบ Java 8 ในเป้าหมายใหม่สองประการ:
การคัดลอกรหัสมีดังนี้:
@target ({elementtype.type_parameter, elementtype.type_use})
@Interface myannotation {}
นั่นคือทั้งหมดที่เกี่ยวกับคุณสมบัติใหม่ของ Java 8 และมีคุณสมบัติเพิ่มเติมที่รอการค้นพบ มีสิ่งที่มีประโยชน์มากมายใน JDK 1.8 เช่น Arrays.Parallelsort, StampedLock และ PrecilableFuture