Java線程池詳細(xì)解讀
1、線程池
線程池就是多個(gè)線程封裝在一起操作。
1.1 線程池概念
在生活中經(jīng)常遇見(jiàn),今天開(kāi)發(fā)一個(gè)項(xiàng)目需要20個(gè)人一起開(kāi)發(fā)
- 這個(gè)活很大,有多少人要多少人
- 這個(gè)活很大,但是要求10個(gè)人
- 這個(gè)活很大,但只要求1個(gè)人做
追加一個(gè)并發(fā)訪問(wèn)的程序報(bào):java.util.concurrent,對(duì)于此線程池的操作的核心類和接口就定義在之中。這里面有兩個(gè)核心的接口:
- 普通的執(zhí)行線程池定義:Interface ExecutorService
- 調(diào)度線程池:Interface ScheduledExecutorService
- 如果要進(jìn)行線程池的創(chuàng)建一般使用Class Executors這個(gè)類
- 創(chuàng)建無(wú)法小限制的線程池:public static ExecutorService newCachedThreadPool()
- 創(chuàng)建固定大小的線程池:public static ExecutorService newFixedThreadPool(int nThreads)
- 單線程池:public static ExecutorService newSingleThreadExecutor()
- 創(chuàng)建定時(shí)調(diào)度池:public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
1.2 線程池的實(shí)現(xiàn)
創(chuàng)建無(wú)限大小的線程池
package com.day13.demo; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class PoolDemo1 { public static void main(String[] args) throws Exception { // TODO Auto-generated method stub //創(chuàng)建了一個(gè)線程池的模型,但是后面沒(méi)有線程 ExecutorService executorService = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { int index = i; Thread.sleep(200); executorService.submit(()-> { System.out.println(Thread.currentThread().getName() + ",i = " + index); }); } executorService.shutdown(); } }
創(chuàng)建固定大小的線程池
package com.day13.demo; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class PoolDemo1 { public static void main(String[] args) throws Exception { // TODO Auto-generated method stub //創(chuàng)建了一個(gè)線程池的模型,但是后面沒(méi)有線程 ExecutorService executorService = Executors.newFixedThreadPool(3); for (int i = 0; i < 10; i++) { int index = i; Thread.sleep(200); executorService.submit(()-> { System.out.println(Thread.currentThread().getName() + ",i = " + index); }); } executorService.shutdown(); } }
創(chuàng)建我們的單線程線程池
package com.day13.demo; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class PoolDemo1 { public static void main(String[] args) throws Exception { // TODO Auto-generated method stub //創(chuàng)建了一個(gè)線程池的模型,但是后面沒(méi)有線程 ExecutorService executorService = Executors.newSingleThreadExecutor(); for (int i = 0; i < 10; i++) { int index = i; executorService.submit(()-> { System.out.println(Thread.currentThread().getName() + ",i = " + index); }); } executorService.shutdown(); } }
定時(shí)調(diào)度池
package com.day13.demo; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class PoolDemo1 { public static void main(String[] args) throws Exception { // TODO Auto-generated method stub //創(chuàng)建了一哥具備有三個(gè)線程大小的定時(shí)調(diào)度池 ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); for (int i = 0; i < 10; i++) { //Thread.sleep(200); int index = i; executorService.scheduleAtFixedRate(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub System.out.println(Thread.currentThread().getName() + ",i = " + index); } }, 3, 2, TimeUnit.SECONDS);//使用的是一個(gè)秒的單位,表示3秒后開(kāi)始執(zhí)行,而后每過(guò)2秒執(zhí)行一次 } } }
線程池給我們開(kāi)發(fā)者帶來(lái)唯一好處的就是允許多個(gè)線程按照組的模式進(jìn)行程序的處理,這樣在一個(gè)業(yè)務(wù)邏輯非常復(fù)雜的情況下,性能就會(huì)得到很好的提升。
2、StringBuffer類
對(duì)于類庫(kù)的學(xué)習(xí),不可能全學(xué)完。你所需要知道就是如何面對(duì)解決問(wèn)題的方法。要學(xué)會(huì)查詢文檔。
StringBuffer類之前首先來(lái)簡(jiǎn)單回顧一下String類的特點(diǎn):
String類的對(duì)象有兩種實(shí)例化方式,一種是直接賦值,只會(huì)開(kāi)辟一塊堆內(nèi)存空間,而且對(duì)象可以自動(dòng)入池,另外一種方式使用構(gòu)造方法完成,會(huì)開(kāi)辟兩塊空間,有一塊空間將稱為垃圾,并且不會(huì)自動(dòng)入池,但是可以通過(guò)intern()方法手工入池;
字符串常亮一旦聲明則不能改變,而字符串對(duì)象可以改變,但是改變的是其內(nèi)存地址的指向;
通過(guò)以上的幾個(gè)特點(diǎn)就可以清楚的發(fā)現(xiàn),String類是表示字符串使用最多的類,但是其不合適于被頻繁修改的字符串操作上,所以在這種情況下,往往可以使用StringBuffer類,即:StringBuffer類方便用戶進(jìn)行內(nèi)容的修改,在String類之中使用“+”作為數(shù)據(jù)庫(kù)的連接操作,而在StringBuffer類之中使用append()方法進(jìn)行數(shù)據(jù)的連接。
使用StringBuffer操作,StringBuffer內(nèi)容可以改變。
package com.day13.demo; public class BufferDemo { public static void main(String[] args) { StringBuffer buf = new StringBuffer(); buf.append("hello").append(",world!"); fun(buf);//修改了buf的內(nèi)容 System.out.println(buf); } public static void fun(StringBuffer tem){ tem.append("\n").append("zsr"); } }
String和StringBuffer最大的區(qū)別就是:String的內(nèi)容無(wú)法修改,而StringBuffer的內(nèi)容可以修改。但是在開(kāi)發(fā)的選擇還是優(yōu)先選擇String類。
現(xiàn)在學(xué)習(xí)的字符串的操作類就有兩個(gè)了:String,StringBuffer,那么下面通過(guò)這兩個(gè)類的定義來(lái)研究一下關(guān)系:
String類: | StringBuffer類: |
public final class String extends Object implements Serializable,Comparable,CharSequence |
public final class StringBuffer extends Object implements Serializable, CharSequence |
可以發(fā)現(xiàn)兩個(gè)類都是“CharSequence”接口的子類。這個(gè)接口描述的是字符集,所以串就屬于字符集的子類,如果以后看見(jiàn)CharSequence最簡(jiǎn)單的聯(lián)想就是字符串。但是有一個(gè)小小的問(wèn)題需要注意一下就是String和StringBuffer兩個(gè)類型無(wú)法直接轉(zhuǎn)換。
利用StringBuffer:利用StringBuffer構(gòu)造方法、append()方法
將String變?yōu)镾tringBuffer
1.直接利用StringBuffer類的構(gòu)造方法,public StringBuffer(String str)
package com.day13.demo; public class BufferTest{ public static void main(String[] args) throws Exception { String str = "Hello World."; StringBuffer buf = new StringBuffer(str); fun(buf); System.out.println(buf); } private static void fun(StringBuffer temp) { temp.append("\n").append("zsr"); } }
2.利用StringBuffer類的append()方法
package com.day13.demo; public class BufferTest{ public static void main(String[] args) throws Exception { String str = "Hello World."; StringBuffer buf = new StringBuffer(); buf.append(str); fun(buf); System.out.println(sb); } private static void fun(StringBuffer temp) { temp.append("\n").append("zsr"); } }
將StringBuffer變成String,利用StringBuffer類的toString()方法完成
package com.day13.demo; public class BufferTest{ public static void main(String[] args) throws Exception { StringBuffer buf = new StringBuffer("hello,World!"); String str = buf.toString(); System.out.println(str); } }
實(shí)際上StringBuffer還是有一些String類所沒(méi)有的特點(diǎn)的。
1.字符串反轉(zhuǎn)操作,public StringBuffer reverse()
package com.day13.demo; public class BufferTest{ public static void main(String[] args) throws Exception { StringBuffer buf = new StringBuffer("hello,World!"); System.out.println(buf.reverse()); } }
2.刪除指定范圍內(nèi)的數(shù)據(jù),public StringBuffer delete(int start, int end)
package com.day13.demo; public class BufferDemo { public static void main(String[] args) { StringBuffer buf = new StringBuffer("Hello,World!"); System.out.println(buf.delete(5, 11)); } }
3.插入數(shù)據(jù)的方法, public StringBuffer insert(int offset, Object obj)
package com.day13.demo; public class BufferDemo { public static void main(String[] args) { StringBuffer buf = new StringBuffer("Hello,World!"); System.out.println(buf.delete(5,11).insert(0, "你好,")); } }
面試題:請(qǐng)解釋String、StringBuffer、StringBuilder的區(qū)別?
- String的內(nèi)容不可以修改,StringBuffer與StringBuilder內(nèi)容可以修改
- StringBuffer采用同步處理屬于線程安全操作,StringBuilder采用異步處理屬于線程不安全操作。
3、Runtime類
在每一個(gè)JVM的進(jìn)程中,都會(huì)存在一個(gè)運(yùn)行時(shí)的操作類的對(duì)象,而這對(duì)象所屬的類型就是Runtime類。打開(kāi)這個(gè)類的文檔,發(fā)現(xiàn)這個(gè)類之中并沒(méi)有構(gòu)造方法的定義,可是按照之前所學(xué),每個(gè)類至少有一個(gè)構(gòu)造方法,而這個(gè)類的構(gòu)造方法實(shí)際上存在只是不被外部看見(jiàn)而已,因?yàn)闃?gòu)造方法私有化了,這是一個(gè)標(biāo)準(zhǔn)的單例設(shè)計(jì)模式,既然是單例設(shè)計(jì)模式則在這個(gè)類之中一定會(huì)存在一個(gè)static型方法,可以取得本類的Runtime實(shí)例化對(duì)象:public static Runtime getRuntime()。
取得了Runtime類之后最主要的功能就是可以通過(guò)它來(lái)觀察當(dāng)前的內(nèi)存操作情況:
方法名稱 | 類型 | 描述 |
public long freeMemory() | 普通 | 取得當(dāng)前空余內(nèi)存空間大小 |
public long totalMemory() | 普通 | 取得當(dāng)前可以使用總空間大小 |
public long maxMemory() | 普通 | 取得最大的可用內(nèi)存空間的大小 |
public native void gc() | 普通 | 執(zhí)行垃圾收集處理 |
觀察一下內(nèi)存信息的取得
package com.day13.demo; public class RuntimeDemo { public static void main(String[] args) { Runtime run = Runtime.getRuntime(); System.out.println("1、MAX=" + byteToM(run.maxMemory())); System.out.println("1、TOTAL=" + byteToM(run.totalMemory())); System.out.println("1、FREE=" + byteToM(run.freeMemory())); } public static double byteToM(long num){ return (double) num / 1024 / 1024; } }
gc垃圾回收
package com.day13.demo; public class RuntimeDemo { public static void main(String[] args) { Runtime run = Runtime.getRuntime(); System.out.println("1、MAX=" + byteToM(run.maxMemory())); System.out.println("1、TOTAL=" + byteToM(run.totalMemory())); System.out.println("1、FREE=" + byteToM(run.freeMemory())); String str = ""; for (int i = 0; i < 2222; i++) { str += i; } System.out.println("2、MAX=" + byteToM(run.maxMemory())); System.out.println("2、TOTAL=" + byteToM(run.totalMemory())); System.out.println("2、FREE=" + byteToM(run.freeMemory())); run.gc();//垃圾收集 System.out.println("3、MAX=" + byteToM(run.maxMemory())); System.out.println("3、TOTAL=" + byteToM(run.totalMemory())); System.out.println("3、FREE=" + byteToM(run.freeMemory())); } public static double byteToM(long num){ return (double) num / 1024 / 1024; } }
面試題:什么叫g(shù)c?如何處理
- gc(Garbage Conllector):垃圾收集器,用于釋放無(wú)用的內(nèi)存空間
- gc有兩種處理形式,一種是自動(dòng)不定期調(diào)用,另外一種是使用Runtime的gc()方法手工處理調(diào)用。
4、System類
實(shí)際上在之前進(jìn)行的數(shù)組拷貝就是運(yùn)用System類中的public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length)
在這個(gè)類中提供有一個(gè)取得當(dāng)前日期時(shí)間數(shù)的方法**public static long currentTimeMillis();**通過(guò)此方法可以取得某一個(gè)操作花費(fèi)的時(shí)間。
觀察currentTimeMillis()的使用
package com.day13.demo; public class SystemDemo { public static void main(String[] args) { long start = System.currentTimeMillis(); String str = ""; for (int i = 0; i < 2222; i++) { str += i; } long end = System.currentTimeMillis(); System.out.println("花費(fèi)時(shí)間:" + (end - start) + "ms"); } }
可是在System類之中還存在了一個(gè)很有意思的方法:public static void gc(),但是這個(gè)gc()方法并不是一個(gè)新的gc()方法而是間接調(diào)用了一個(gè)Runtime類之中的gc()方法,不表示一個(gè)重寫的方法。
在之前一直強(qiáng)調(diào)過(guò)一個(gè)概念:一個(gè)類對(duì)象的創(chuàng)建一定要使用構(gòu)造方法,那么一個(gè)對(duì)象不使用構(gòu)造方法了,就一個(gè)被釋放,被釋放的時(shí)候一改也有一個(gè)方法進(jìn)行支持才對(duì)。所以要想做這種收尾的操作,可以讓一個(gè)類去覆寫object中的finalize()方法。此方法由Object類定義:protected void finalize() throws Throwable。在對(duì)象回收之前有可能出現(xiàn)異?;蛘咤e(cuò)誤,但是即使出現(xiàn)了也不會(huì)影響程序的執(zhí)行,即:不會(huì)因?yàn)楫惓6鴮?dǎo)致程序的中斷執(zhí)行。
finalize()方法使用
package com.day13.demo; class Person{ public Person(){ System.out.println("問(wèn)啊娃娃,出來(lái)了!"); } @Override protected void finalize() throws Throwable { // TODO Auto-generated method stub System.out.println("我要下地獄了,下輩子不要當(dāng)人了——"); throw new Exception("繼續(xù)要活幾千年"); } } public class FinalizeDemo { public static void main(String[] args) { Person person = new Person(); person = null; System.out.println("已經(jīng)轉(zhuǎn)世不為人了"); System.gc(); } }
面試題:請(qǐng)解釋final、finally、finalize的區(qū)別?
- final是一個(gè)關(guān)鍵字,用于定義不能夠被繼承的父類、不能夠覆寫的常量
- finally是異常處理的統(tǒng)一出口
- finalize是Object類中的方法,用于在對(duì)象回收前進(jìn)行調(diào)用
5、對(duì)象克隆
克隆就是對(duì)象復(fù)制的一個(gè)概念,不過(guò)這種概念一般使用的比較少,因?yàn)楹苌儆腥巳?fù)制已經(jīng)存在的對(duì)象。Object類本身就支持對(duì)象克隆方法??梢园l(fā)現(xiàn)protected Object clone() throws CloneNotSupportedException;我們要想實(shí)現(xiàn)克隆,那么我們并不是所有類的對(duì)象可以隨便克隆,需要被克隆的對(duì)象所在類一定要實(shí)現(xiàn)Cloneable接口,而最關(guān)鍵的是該接口并沒(méi)有任何的抽象方法,所以該接口只是一個(gè)標(biāo)識(shí)接口,表示一種能力。
對(duì)象克隆實(shí)現(xiàn)
package com.day13.demo; class Per implements Cloneable{//必須實(shí)現(xiàn)此接口 private String name; private int age; public Per(String name, int age) { super(); 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 "Per [name=" + name + ", age=" + age + "]"; } @Override //覆寫權(quán)限擴(kuò)大 protected 擴(kuò)大到 public public Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub return super.clone();//父類負(fù)責(zé)克隆 } } public class CloneDemo { public static void main(String[] args) throws Exception{ Per perA = new Per("kaco",12); //perA.clone();不能在這寫的原因是因?yàn)榇朔椒ㄊ莗rotected權(quán)限 只能在不同包的子類中實(shí)現(xiàn)此方法 Per perB = (Per) perA.clone(); perB.setAge(100); System.out.println(perA); System.out.println(perB); } }
意義不大,需要清楚表示接口的作用,表示的是一個(gè)能力。
6、Date類
日期數(shù)據(jù)類型一定要重視,所有的開(kāi)發(fā)必定要有日期。
6.1 日期處理類—Date類
java.util.data類是在整個(gè)程序處理之中唯一可以取得日期當(dāng)前日期實(shí)例化對(duì)象的操作方法,也就是說(shuō)我們要取出當(dāng)前日期輸出Date類對(duì)象即可。
package com.day13.demo; import java.util.Date; public class DateDemo1 { public static void main(String[] args) { Date date = new Date(); //Tue Aug 17 17:01:50 CST 2021 System.out.println(date); } }
在Date類中最需要關(guān)心的一個(gè)核心問(wèn)題:long可以描述日期,看了一通過(guò)Date類中提供的方法來(lái)進(jìn)行觀察。
方法名稱 | 類型 | 描述 |
public Date(long date) | 普通 | 將long類型變?yōu)镈ate類型數(shù)據(jù) |
public long getTime() | 普通 | 將Date類型變?yōu)閘ong類型數(shù)據(jù) |
觀察轉(zhuǎn)化
package com.day13.demo; import java.util.Date; public class DateDemo1 { public static void main(String[] args) { long num = System.currentTimeMillis(); System.out.println(new Date(num)); System.out.println(new Date(num).getTime()); } }
這中簡(jiǎn)單的轉(zhuǎn)換在以后的程序開(kāi)發(fā)經(jīng)常會(huì)使用。
6.2 日期格式化—SimpleDateFormat類(核心)
雖然Date可以取得當(dāng)前的日期時(shí)間,但是取出的結(jié)構(gòu)不是我們所喜歡的格式,這時(shí)候就需要我們進(jìn)行格式的轉(zhuǎn)化,使用的是java.text包
但是日期格式里面需要設(shè)置一些日期標(biāo)記:年(YYYY)、月(MM)、日(dd)、時(shí)(HH)、分(mm)、秒(ss)、毫秒(SS);
實(shí)現(xiàn)日期格式化處理(日期格式化之后是字符串)
package com.day13.demo; import java.text.SimpleDateFormat; import java.util.Date; public class DateDemo1 { public static void main(String[] args) { Date date = new Date(); String str = "YYYY-MM-dd HH:mm:ss"; SimpleDateFormat sdf = new SimpleDateFormat(str); String dateFromat = sdf.format(date); System.out.println(dateFromat); } }
將字符串變?yōu)镈ate類型
package com.day13.demo; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class DateDemo2 { public static void main(String[] args) throws ParseException{ Date date = new Date(); System.out.println(date); String str = "yyyy-MM-dd HH:mm:ss"; SimpleDateFormat sdf = new SimpleDateFormat(str); //將Date類型轉(zhuǎn)化為字符串類型 String newdateStirng = sdf.format(date); System.out.println(newdateStirng); //將字符串轉(zhuǎn)化為Date類型 Date newdate = sdf.parse(newdateStirng); System.out.println(newdate); } }
7、 數(shù)字操作類—Math類
在Java.lang.Math類之中定義了所有的于數(shù)學(xué)有關(guān)的基本公式,在這個(gè)類之中所有的方法都是static型的方法,強(qiáng)調(diào)一個(gè)方法:round(),public static long round(double a),表示四舍五入。
package com.day13.demo; public class MathDemo { public static void main(String[] args) { System.out.println(Math.round(13.51)); System.out.println(Math.round(13.5)); //如果負(fù)數(shù)小數(shù),沒(méi)大于0.5都不進(jìn)位 System.out.println(Math.round(-13.51)); System.out.println(Math.round(-13.5));//-13 } }
希望可以準(zhǔn)確的保存小數(shù)位進(jìn)行處理。
需要保留幾位小數(shù)
package com.day13.demo; class MyMath{ public static double round(double num, int scale){ return Math.round(num * Math.pow(10, scale)) / Math.pow(10, scale); } } public class MathDemo { public static void main(String[] args) { //1234.457 System.out.println(MyMath.round(1234.4567, 3)); } }
7.1 隨機(jī)數(shù)—Random()
Java .util.Random的主要主要作用就是產(chǎn)生隨機(jī)數(shù),下面通過(guò)一個(gè)代碼來(lái)觀察就行。
網(wǎng)站開(kāi)發(fā)的隨機(jī)驗(yàn)證碼
package com.day13.demo; import java.util.Random; public class RandomDemo { public static void main(String[] args) { char data [] = new char[]{'a','b','c','d','e'}; for (int i = 0; i < 4; i++) { System.out.print(data[new Random().nextInt(data.length)]); } } }
7.2 大數(shù)字操作類
如果說(shuō)現(xiàn)在有兩個(gè)非常大的數(shù)字要進(jìn)行數(shù)學(xué)操作,你們認(rèn)為要怎么做?這個(gè)時(shí)候數(shù)字已經(jīng)超過(guò)了double的范圍,那么只能利用字符串來(lái)表示,取出每一個(gè)字符串變?yōu)閿?shù)字后進(jìn)行數(shù)學(xué)計(jì)算,這種方式的難度較高,為了解決這種問(wèn)題,在Java之中提供了兩個(gè)大數(shù)字操作類:java.math包中BigInteger,BigDecimal,而這兩個(gè)類是屬于Number的子類。
1.大整數(shù)操作類:BigIntegr
之前已經(jīng)強(qiáng)調(diào)過(guò)了,如果數(shù)字較大,肯定按照String來(lái)處理,所以這一點(diǎn)可以通過(guò)Biginteger的構(gòu)造方法來(lái)觀察:
構(gòu)造:public BigInteger(String val);
而且在BigInteger類之中定義了一些基本的數(shù)學(xué)計(jì)算:
加法:public BigInteger add(BigInteger val);
減法:public BigInteger subtract(BigInteger val);
乘法:public BigInteger multiply(BigInteger val);
除法(不保存余數(shù)):public BigInteger divide(BigInteger val);
除法(保存余數(shù)):public BigInteger divideAndRemainder(BigInteger val)
大數(shù)的四則運(yùn)算
package com.day13.demo; import java.math.BigInteger; public class BigAddDemo { public static void main(String[] args) { BigInteger bigA = new BigInteger("123712487812974891274891274128947891"); BigInteger bigB = new BigInteger("43895748395789347589347589398"); System.out.println("加法計(jì)算:" + bigA.add(bigB)); System.out.println("減法計(jì)算:" + bigA.subtract(bigB)); System.out.println("乘法計(jì)算:" + bigA.multiply(bigB)); System.out.println("除法計(jì)算:" + bigA.divide(bigB)); BigInteger result[] = bigA.divideAndRemainder(bigB); System.out.println("除法計(jì)算:" + result[0] + "." + result[1]); } }
2.大小數(shù)操作類:BigDcimal
BigDecimal類表示的是大小數(shù)操作類,但是這個(gè)類也具備了于之前同樣的基本計(jì)算方式,而在實(shí)際的工作之中,是用這個(gè)類最多的情況是進(jìn)行準(zhǔn)確位數(shù)的四舍五入操作,如果要完成這一操作需要關(guān)心BigDecimal類中的以下定義:
構(gòu)造:public BigDecimal(double val);
除法:public BigDecimal divide(BigDecimal divisor ,int scale ,int roundingMode);
進(jìn)位模式:public static final int ROUND_HALF_UP。
四舍五入進(jìn)位操作
package com.day13.demo; import java.math.BigDecimal; //大數(shù)進(jìn)位方法 class MyMath1{ public static double round(double num, int scale){ return new BigDecimal(num).divide(new BigDecimal(1), scale, BigDecimal.ROUND_HALF_DOWN).doubleValue(); } } public class BigDecimalDemo { public static void main(String[] args) { System.out.println(MyMath1.round(2138845.4567, 3)); } }
8、Arrays類
排序操作:java.util.Arrays.sort(數(shù)組名稱),對(duì)于Arrays類一直是進(jìn)行數(shù)組排序的操作,類一直進(jìn)行數(shù)組排序的操作,而Arrays類是定義在java.util包下的一個(gè)操作類,在這個(gè)類之中定義了所有的與數(shù)組有關(guān)的基本操作:二分查找,拷貝操作,相等判斷,填充,變?yōu)樽址敵龅取?/p>
package com.day13.demo; import java.util.Arrays; public class ArraysDemo { public static void main(String[] args) { int dataA[] = new int []{1,2,3,4,5,6}; int dataB[] = new int []{1,2,3,4,5,6}; //數(shù)組輸出 System.out.println(Arrays.toString(dataA)); //兩個(gè)數(shù)組進(jìn)行比較 System.out.println(Arrays.equals(dataA,dataB)); //數(shù)組二分法查找 System.out.println(Arrays.binarySearch(dataA, 4)+1); } }
9、比較器—Comparable
9.1 Comparable
對(duì)象數(shù)組排序:public static void sort(Object[] a)
package com.day13.demo; import java.util.Arrays; class Pers{ private String name; private int age; public Pers(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 "Pers [name=" + name + ", age=" + age + "]"; } } public class ComparableDemo { public static void main(String[] args) { Pers pers[] = new Pers[]{ new Pers("張三",12), new Pers("李四",23), new Pers("劉武",54)//對(duì)象數(shù)組 }; Arrays.sort(pers);//要進(jìn)行對(duì)象數(shù)組的排序處理 System.out.println(Arrays.toString(pers)); } }
這個(gè)時(shí)候沒(méi)有任何的語(yǔ)法錯(cuò)誤,即:程序的代碼是正確的,但是在程序執(zhí)行的時(shí)候出現(xiàn)了以下的問(wèn)題:
Exception in thread "main" java.lang.ClassCastException: com.day13.demo.Pers cannot be cast to java.lang.Comparable at java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:320) at java.util.ComparableTimSort.sort(ComparableTimSort.java:188) at java.util.Arrays.sort(Arrays.java:1246) at com.day13.demo.ComparableDemo.main(ComparableDemo.java:36)
明確的告訴用戶現(xiàn)在發(fā)生了“ClassCaseException”,類轉(zhuǎn)換異常,Person類不能變?yōu)镃omparables實(shí)例。
如果要為對(duì)象指定比較規(guī)則,那么對(duì)象所在的類必須實(shí)現(xiàn)Comparable接口,下面首先來(lái)看一下這個(gè)接口的定義:
public interface Comaparable<T>{ public int compareTo(T o) }
Stirng類中的compareTo()就屬于覆寫Comaparable接口所的來(lái)的方法。
實(shí)現(xiàn)對(duì)象數(shù)組的排序
package com.day13.demo; import java.util.Arrays; class Pers implements Comparable<Pers>{ private String name; private int age; public Pers(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 "Pers [name=" + name + ", age=" + age + "]\n"; } @Override public int compareTo(Pers o) { // TODO Auto-generated method stub //升序排序 如果降序排序?qū)? 和 -1 進(jìn)行位置調(diào)換 if(this.age > o.age){ return -1; }else if(this.age < o.age){ return 1; }else{ return 0; } } } public class ComparableDemo { public static void main(String[] args) { Pers pers[] = new Pers[]{ new Pers("張三",12), new Pers("李四",23), new Pers("劉武",54)//對(duì)象數(shù)組 }; Arrays.sort(pers);//要進(jìn)行對(duì)象數(shù)組的排序處理 System.out.println(Arrays.toString(pers)); } }
只要是對(duì)象數(shù)組排序,就必須有Comparable接口。
9.2 二叉樹(shù)( Binary Tree )
二叉樹(shù)是一種排序的基本的數(shù)據(jù)結(jié)構(gòu),而如果要想為多個(gè)對(duì)象進(jìn)行排序,那么就必須可以區(qū)分出對(duì)象的大小,那么就必須依靠Comparable接口完成。
二叉樹(shù)的基本原理:取第一個(gè)元素作為根節(jié)點(diǎn),之后每一個(gè)元素的排列要求:如果比根節(jié)點(diǎn)曉得數(shù)據(jù)放在左子樹(shù),如果比根節(jié)點(diǎn)大的數(shù)據(jù)放在右子樹(shù),在輸出的時(shí)候采用中序(左-根-右)遍歷的方式完成。
但是不管是何種方式操作,一定要記住,這種數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn)永遠(yuǎn)都需要依靠節(jié)點(diǎn)類,而這個(gè)時(shí)候的節(jié)點(diǎn)類要保存兩個(gè)節(jié)點(diǎn):左,右。
10、國(guó)際化
在java.util.Locale可以找java提供國(guó)際化的相關(guān)信息
Locale構(gòu)造:public Locale(String language, String country)
觀察區(qū)域和語(yǔ)言代碼
package com.day13.demo; import java.util.Locale; public class LocalDemo { public static void main(String[] args) { System.out.println(Locale.CHINA);//zh_CN System.out.println(Locale.CHINESE);//zh } }
- 中國(guó)Locale:public static final Locale CHINESE
- 美國(guó)Locale:public static final Locale US
- 取得當(dāng)前的Locale對(duì)象:public static Locale getDefault()
當(dāng)我們用eclipse打開(kāi)Message.properties進(jìn)行編寫后不要慌,我們還有一個(gè)非常強(qiáng)大的工具在JDK中,CLASSPATH:C:\Program Files\Java\jdk1.8.0_241\bin 自己安裝JDK的環(huán)境目錄下有一個(gè)叫native2ascii.exe可以幫助我們進(jìn)行轉(zhuǎn)碼。這種做法非常麻煩,如果要開(kāi)發(fā)國(guó)際版本的軟件還是自己安裝一個(gè)編輯軟件比較好。
語(yǔ)言配置文件Message.properties
welcome.info = \u5317\u4EAC\u6B22\u8FCE\u4F60\uFF01
測(cè)試文件LocaleDemo.java
package com.day13.demo; import java.util.ResourceBundle; public class LocaleDemo { public static void main(String[] args) { //這個(gè)時(shí)候設(shè)置的baseName沒(méi)有后綴,而且一定要在CLASSPATH之中 ResourceBundle res = ResourceBundle.getBundle("com.day13.msg.Message"); //北京歡迎你! System.out.println(res.getString("welcome.info")); } }
資源文件的名稱就只是 包.名稱前綴
到此這篇關(guān)于Day13基礎(chǔ)不牢地動(dòng)山搖-Java基礎(chǔ)的文章就介紹到這了,更多相關(guān)Java基礎(chǔ)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Intellij IDEA如何自定義注釋模板的實(shí)現(xiàn)方法
這篇文章主要介紹了Intellij IDEA如何自定義注釋模板的實(shí)現(xiàn)方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-05-05關(guān)于SpringMVC在Controller層方法的參數(shù)解析詳解
在SpringMVC中,控制器Controller負(fù)責(zé)處理由DispatcherServlet分發(fā)的請(qǐng)求,下面這篇文章主要給大家介紹了關(guān)于SpringMVC在Controller層方法的參數(shù)解析的相關(guān)資料,需要的朋友可以參考下2021-12-12微信公眾號(hào)支付(二)實(shí)現(xiàn)統(tǒng)一下單接口
本篇文章主要給大家介紹調(diào)用微信公眾支付的統(tǒng)一下單API,通過(guò)參數(shù)封裝為xml格式并發(fā)送到微信給的接口地址就可以獲得返回內(nèi)容,需要的朋友可以參考下本文2015-09-09詳解SpringBoot構(gòu)建Docker鏡像的3種方式
這篇文章主要介紹了SpringBoot構(gòu)建Docker鏡像的3種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06Spring使用@Filter注解創(chuàng)建自定義過(guò)濾器
Spring 中鮮為人知但非常有用的注解之一是 @Filter,它支持自定義過(guò)濾器,下面我們就來(lái)深入研究一下如何使用 Spring 的 @Filter 注解來(lái)創(chuàng)建自定義過(guò)濾器吧2023-11-11POST方法給@RequestBody傳參數(shù)失敗的解決及原因分析
這篇文章主要介紹了POST方法給@RequestBody傳參數(shù)失敗的解決及原因分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10