一.Comparator接口java
*Comparator接口的使用程序員
(1)使用Comparable接口定義排序順序有侷限性:實現此接口的類只能按compareTo()定義的這一種方式排序。編程
(2)若是同一類對象要有多種排序方式,應該爲該類定義不一樣的比較器(實現Comparator接口的類)TreeSet有一個構造方法容許給定比較器,它就會根據給定的比較器對元素進行排序.數組
(3)Comparator接口中的比較方法多線程
示例:public int compare(Object o1, Object o2); app
該方法若是ide
返回 0,表示 o1 == o2測試
返回正數,表示 o1 > o2ui
返回負數,表示 o1 < o2this
例(以學生成績排名爲例):
學生類(Student):
package comparator;
public class Student {
private String name;
private int score;//總分
private int math;//語文成績
public Student() {
super();
}
public Student(String name, int score, int math) {
super();
this.name = name;
this.score = score;
this.math = math;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public int getMath() {
return math;
}
public void setMath(int math) {
this.math = math;
}
@Override
public String toString() {
return "Student [name=" + name + ", score=" + score + ", math=" + math
+ "]";
}
}
以總分爲第一排序準則類(ScoreRule):
package comparator;
import java.util.*;
public class ScoreRule implements Comparator<Student> {
@Override
public int compare(Student stu1, Student stu2) {
if(stu1.getScore()>stu2.getScore()){
return -1;
}else if(stu1.getScore()<stu2.getScore()){
return 1;
}else{
if(stu1.getMath()>stu2.getMath()){
return -1;
}else if(stu1.getMath()<stu2.getMath()){
return 1;
}else{
return stu1.getName().compareTo(stu2.getName());
}
}
}
}
以數學成績爲第一標準排序類(MathRule):
package comparator;
import java.util.Comparator;
public class MathRule implements Comparator<Student>{
@Override
public int compare(Student stu1, Student stu2) {
if(stu1.getMath()>stu2.getMath()){
return -1;
}else if(stu1.getMath()<stu2.getMath()){
return 1;
}else{
if(stu1.getScore()>stu2.getScore()){
return -1;
}else if(stu1.getScore()<stu2.getScore()){
return 1;
}else{
return stu1.getName().compareTo(stu2.getName());
}
}
}
}
測試TreeSet類:
package comparator;
import java.util.TreeSet;
public class TestSetDemo {
public static void main(String[] args) {
TreeSet<Student> set=new TreeSet<Student>(new ScoreRule());
set.add(new Student("獨孤求敗",786,145));
set.add(new Student("王磊",456,78));
set.add(new Student("王忠磊",564,97));
set.add(new Student("風清揚",786,123));
set.add(new Student("王磊",456,78));
set.add(new Student("王磊",456,78));
set.add(new Student("楊過",456,98));
set.add(new Student("令狐沖",556,86));
set.add(new Student("張無忌",665,100));
set.add(new Student("獨孤求敗",786,145));
set.add(new Student("孫悟空",754,147));
set.add(new Student("唐僧",453,67));
System.out.println("以總分爲 排序第一標準:");
for(Student stu:set){
System.out.println(stu);
}
System.out.println();
TreeSet<Student> set1=new TreeSet<Student>(new MathRule());
set1.add(new Student("獨孤求敗",786,145));
set1.add(new Student("王磊",456,78));
set1.add(new Student("王忠磊",564,97));
set1.add(new Student("風清揚",786,123));
set1.add(new Student("王磊",456,78));
set1.add(new Student("王磊",456,78));
set1.add(new Student("楊過",456,98));
set1.add(new Student("令狐沖",556,86));
set1.add(new Student("張無忌",665,100));
set1.add(new Student("獨孤求敗",786,145));
set1.add(new Student("孫悟空",754,147));
set1.add(new Student("唐僧",453,67));
System.out.println("以數學成績爲第一排序標準:");
for(Student stu:set1){
System.out.println(stu);
}
}
}
運行結果爲:
以總分爲 排序第一標準:
Student [name=獨孤求敗, score=786, math=145]
Student [name=風清揚, score=786, math=123]
Student [name=孫悟空, score=754, math=147]
Student [name=張無忌, score=665, math=100]
Student [name=王忠磊, score=564, math=97]
Student [name=令狐沖, score=556, math=86]
Student [name=楊過, score=456, math=98]
Student [name=王磊, score=456, math=78]
Student [name=唐僧, score=453, math=67]
以數學成績爲第一排序標準:
Student [name=孫悟空, score=754, math=147]
Student [name=獨孤求敗, score=786, math=145]
Student [name=風清揚, score=786, math=123]
Student [name=張無忌, score=665, math=100]
Student [name=楊過, score=456, math=98]
Student [name=王忠磊, score=564, math=97]
Student [name=令狐沖, score=556, math=86]
Student [name=王磊, score=456, math=78]
Student [name=唐僧, score=453, math=67]
分析:例中分別以學生的總分和數學分數爲第一標準進行了排序,屬於同一對象多種排序,故咱們實現了Comparator接口實現了接口中的public int compare(Object o1, Object o2)方法,分別制定了各類排序得規則(即比較器),TreeSet中的構造方法容許給定比較器,按照比較器進行排序。
二.Map集合
1.特色:
(1)實現Map接口的集合類用來存儲「鍵-值」映射對。
(2)不能包含重複的鍵,每一個鍵最多隻能映射到一個值,值能夠重複。
(3)JDK API中Map接口的實現類經常使用的有:
HashMap
TreeMap
Hashtable (不經常使用)
Properties
2.Map接口中的經常使用方法:
(1)Object put(Object key, Object value); //將指定的「鍵-值」對存入Map中
(2)Object get(Object key); //返回指定鍵所映射的值
(3)Object remove(Object key); //根據指定的鍵把此「鍵-值」對從Map中移除。
(4)boolean containsKey(Object key); //判斷此Map是否包含指定鍵的「鍵-值」對。
(5)boolean containsValue(Object value); //判斷此Map是否包含指定值的「鍵-值」對。
(6)boolean isEmpty(); //判斷此Map中是否有元素。
(7)int size(); //得到些Map中「鍵-值」對的數量。
(8)void clear(); //清空Map中的全部「鍵-值」對。
(9)Set keySet(); //返回此Map中包含的鍵的Set集。
(10)Collection values(); //返回此Map中包含的值的Collection集。
(11)Set<Map.Entry<K,V>> entrySet() 將全部包含鍵-值對的Map.Entry收集到Set
3.Map.Entry接口:
*Map.Entry是Map中內部定義的一個接口,專門用來保存key value的內容。
4.HashMap類與TreeMap類
(1)HashMap存儲結構使用哈希表,使用「鍵」進行散列存放。因此根據「鍵」去取「值」的效率很高。
(2)TreeMap中的「key-value」對的「key」必須是可「排序」的。
5.HashTable類
(1)舊版的Hashtable,操做大多跟HashMap相同,只是它保證線程的同步。
(2)它有一個子類Properties(屬性集)比較經常使用:
*Properties 類表示了一個持久的屬性集。Properties 可保存在流中或從流中加載。屬性集中每一個鍵及其對應值都是一個字符串。
*不建議使用 put 和 putAll 這類存放元素方法,應該使用 setProperty(String key, String value)方法,由於存放的「鍵-值」對都是字符串。相似取值也應該使用getProperty(String key)。
例(以Properties類舉例):
package mapdemo;
import java.util.Properties;
public class PropertiesDemo {
public static void main(String[] args) {
Properties pro=new Properties();
pro.setProperty("張三丰","149歲");
pro.setProperty("奧運會","08中國");
pro.setProperty("游泳冠軍","孫楊");
pro.setProperty("六脈神劍","段譽");
pro.setProperty("降龍十八掌","郭靖");
System.out.println("根據鍵找到對應的值:"+pro.getProperty("奧運會"));
System.out.println(pro.getProperty("游泳冠軍"," "));
System.out.println(pro.getProperty("iguihejg","沒有 找到對應的值,這是默認值~~~ "));
}
}
運行結果爲:
根據鍵找到對應的值:08中國
孫楊
沒有 找到對應的值,這是默認值~~~
HashMap和Hashtable區別:
(1) HashMap不一樣步,Hashtable同步
(2) HashMap能夠存儲null鍵null值,Hashtable不能夠
(3) HashMap多線程操做環境下效率高,Hashtable多線程操做環境下效率低
例(以Map集合及其經常使用方法爲例):
package mapdemo;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class HashMapDemo {
public static void main(String[] args) {
HashMap<String, String> map=new HashMap<>();
map.put("country", "中國");
map.put("name", "令狐沖");
map.put("apple", "蘋果");
map.put("banana", "香蕉");
map.put("sing", "唱歌");
map.put("map", "集合");
System.out.println("原始集合鍵值對數:"+map.size());
System.out.println("集合中以country爲Key的鍵值是:"+map.get("country"));
map.remove("name");//移除name鍵值對
System.out.println("移除name集合中以name爲Key的鍵值是:"+map.get("name"));
System.out.println("如今集合鍵值對數:"+map.size());
System.out.println("集合中包括key是banana的鍵值對嗎? "+map.containsKey("banana"));
System.out.println("集合中包括value是蘋果的鍵值對嗎? "+map.containsValue("蘋果"));
Set<String>set=map.keySet();
System.out.println("獲取集合中全部的key,遍厲得:");
for(String str:set){
System.out.print(str+" ");
}
System.out.println();
System.out.println("獲取集合中全部的value值,並遍厲得:");
Collection<String> set1=map.values();
for(String str:set1){
System.out.print(str+"\t");
}
System.out.println();
System.out.println("**********遍厲集合中的全部鍵值對*********");
Set<Map.Entry<String, String>> setEntry=map.entrySet();
for(Map.Entry<String, String> ma:setEntry){
System.out.println(ma.getKey()+"========>"+ma.getValue());
}
}
}
運行結果爲:
原始集合鍵值對數:6
集合中以country爲Key的鍵值是:中國
移除name集合中以name爲Key的鍵值是:null
如今集合鍵值對數:5
集合中包括key是banana的鍵值對嗎? true
集合中包括value是蘋果的鍵值對嗎? true
獲取集合中全部的key,遍厲得:
banana country apple sing map
獲取集合中全部的value值,並遍厲得:
香蕉 中國 蘋果 唱歌 集合
**********遍厲集合中的全部鍵值對*********
banana========>香蕉
country========>中國
apple========>蘋果
sing========>唱歌
map========>集合
三.異常機制
異常的概念:異常是指在程序的運行過程當中所發生的不正常的事件,它會中斷正在運行的程序
Java中如何進行異常處理:Java的異常處理是經過5個關鍵字來實現的:
(1)try執行可能產生異常的代碼
(2)Catch捕獲異常
(3)Finally不管是否產生異常總能執行的代碼
*其上三個 關鍵字 都屬於捕獲異常的範疇
(4)throws聲明方法可能要拋出的各類異常
*throws屬於聲明異常
(5)Throw手動跑出異常對象
*throw屬於拋出異常
3.Java程序編譯和運行時所發生的問題有兩大類:
(1)錯誤(Error):JVM系統內部錯誤或資源耗盡等嚴重狀況-屬於JVM須要負擔的責任
(2)異常(Exception):其它因編程錯誤或偶然的外在因素致使的通常性問題。
*程序員只能處理異常而對錯誤無能爲力
4.異常處理機制的原理:Java程序在執行過程當中若是出現異常,會自動生成一個異常類對象,該異常類對象將被自動提交給JVM(在程序沒有顯式處理異常的情下),這個過程稱爲拋出異常(throw)
5.異常的分類:
(1)檢查時異常(E xception):SQLException,
IOException,
ClassNotFoundException,
......
例(檢查時異常):
package exceptiondemo;
import java.io.IOException;
public class CheckExceptionDemo {
public static void main(String[] args) {
Runtime run=Runtime.getRuntime();
try {
run.exec("clac");
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
運行結果爲:
Cannot run program "clac": CreateProcess error=2, 系統找不到指定的文件。
(2)運行時異常(RunTimeException):NullPointerException,
ArithmeticExcepttion,
ClassCastExceptioion,
ArrayIndexOutOfBundsException,
.......
(3)常見異常:(RunTimeException)
ArithmeticException:數學計算異常
NullPointerException:空指針異常
ArrayOutOfBoundsException:數組索引越界異常
ClassCastException:類型轉換異常
6.Exception與RuntimeException
(1)Exception在程序中是必須進行處理
(2)RuntimeException能夠不使用try…catch進行處理,可是若是有異常產生,則異常將由JVM進行處理。
7.處理異常的方法:
*使用try-catch塊捕獲異常,catch塊能夠有多個
格式以下:
public void method(){
try {
// 代碼段(此處可能產生異常)
} catch (異常類型 ex) {
// 對異常進行處理的代碼段
}
// 代碼段
}
例(以0做爲除數爲例):
package exceptiondemo;
public class TryCatchDemo {
public static void main(String[] args) {
try {
int a=99;
int b=0;
int temp=a/b;
} catch (Exception e) {
System.out.println("產生異常了~~~");
System.out.println("輸出捕獲道德異常"+e.getMessage());
}
System.out.println("程序繼續向下運行!!。。。。");
}
}
運行結果爲:
產生異常了~~~
輸出捕獲道德異常/ by zero
程序繼續向下運行!!。。。。
8.常見的異常類型:
異常類型 |
說明 |
Exception |
異常層次結構的父類 |
ArithmeticException |
算數錯誤情形,如以0做除數 |
ArrayIndexOutOfBoundsException |
數組下標越界 |
NullPointerException |
嘗試訪問null對象成員 |
ClassNotFoundException |
不能加載所需的類 |
IllegalArgumentException |
方法接收到非法參數 |
ClassCastException |
對象強制類型轉換出錯 |
NumberFormatException |
數字格式轉換異常,例「abc」轉換成數字 |
9.try--catch--finally:
(1)在try--catch模塊後加上finally代碼塊,不管是否發生異常,finally中的代碼都會執行
(2)有一種狀況例外:在try--cathch塊後加了System.exit(0),會直接關閉JVM
例(仍是以0做除數爲例):
package exceptiondemo;
public class FinallyDemo {
public static void main(String[] args) {
try {
int result=divide(99,0);
System.out.println("計算結果爲:"+result);
} catch (Exception e) {
System.out.println("出現異常了~~~~");
System.out.println("輸出異常信息:"+e.getMessage());
}finally{
System.out.println("進入finally塊程序繼續運行:");
int x=1;
int y=1;
int temp=x+y;
System.out.println("計算結果爲:"+temp);
}
System.out.println("進入主方法程序繼續向下運行!!!!!!");
}
public static int divide(int x,int y){
int result=x/y;
return result;
}
}
運行結果爲:
出現異常了~~~~
輸出異常信息:/ by zero
進入finally塊程序繼續運行:
計算結果爲:2
進入主方法程序繼續向下運行!!!!!!
10.多重catch塊(引起多種類型的異常):
(1)排列catch塊語句順序:先子類後父類
(2)發生異常時按順序逐個匹配
(3)只執行第一個與異常類型匹配的catch語句
格式:
public void method(){
try {
// 代碼段
// 產生異常(異常類型2)
} catch (異常類型1 ex) {
// 對異常進行處理的代碼段
} catch (異常類型2 ex) {
// 對異常進行處理的代碼段
} catch (異常類型3 ex) {
// 對異常進行處理的代碼段
}
// 代碼段
}
例(挨個捕捉異常):
package exception;
public class RuntimeExceptionDemo {
public static void main(String[] args) {
int a=100;
int b=0;
String str=null;
int[] array=new int[5];
try{
array[5]=100;
str.equals("abc");
int c=a/b;
}catch(NullPointerException e){
System.out.println("空指針異常~~~");
}catch(ArithmeticException e){
System.out.println("算數異常~~~");
}catch(Exception e){
System.out.println("以上catch都沒有捕獲到異常,由最大父類Exception處理異常");
}finally{
System.out.println("進入finally塊不管異常是否發生,都會執行");
}
System.out.println("main()方法執行完畢!");
}
}
運行結果爲:
以上catch都沒有捕獲到異常,由最大父類Exception處理異常
進入finally塊不管異常是否發生,都會執行
main()方法執行完畢!
11.try---finally:try…finally 不能捕獲異常 ,僅僅用來當發生異常時,用來釋放資源
格式:
public void method(){
try {
// 代碼段 1
// 產生異常的代碼段 2
}finally{
// 代碼段 3
}
}
例(以0做除數爲例):
package exceptiondemo;
public class TryFinallyDemo {
public static void main(String[] args) {
try {
int x=88;
int y=0;
int temp=x/y;
System.out.println("計算結果爲:"+temp);
} finally {
System.out.println("用於釋放資源");
}
}
}
運行結果爲:
用於釋放資源
Exception in thread "main" java.lang.ArithmeticException: / by zero
at exceptiondemo.TryFinallyDemo.main(TryFinallyDemo.java:9)
由結果可知try--finally不會捕獲異常,只用於釋放資源
12.throw與throws的區別:
(1)throw用來手動拋出異常
(2)Throws用於方法聲明處,用於拋出該方法體內部可能發生的異常類型。一旦在方法聲明處經過throws拋出某種類型的異常,則在該方 法體內部就不用處理該類型的異常,交給方法調用到處理該類型的異常。
例1(手動拋出異常):
package throwdemo;
public class ThrowDemo {
public static void main(String[] args) {
try {
int[] a=new int[3];
System.out.println(a[4]);
//throw new ArrayIndexOutOfBoundsException();
} catch (Exception e) {
System.out.println("發生了數組越界異常~~~");
}
}
}
運行結果爲:
發生了數組越界異常~~~
例2(throws聲明異常):
package throwsdemo;
public class ThrowsDemo {
public static void main(String[] args) {
try {
int result=divide(88,2);
System.out.println("計算結果爲:"+result);
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
public static int divide(int x,int y) throws Exception{
int result=x/y;
return result;
}
}
運行結果爲:
計算結果爲:44
*注意在調用異常聲明方法是,若是不知道如何處理異常,也可以使用throw關鍵字繼續將異常拋出,這樣程序也能夠編譯經過,但程序一旦發生異常,若是程序沒有被處理,程序就會非正常終止
例:
package throwsdemo;
public class ThrowsDemo01 {
public static void main(String[] args) throws Exception {
int result=divide(88,0);
System.out.println("計算結果爲:"+result);
}
public static int divide(int x,int y) throws Exception{
int result=x/y;
return result;
}
}
運行結果爲:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at throwsdemo.ThrowsDemo01.divide(ThrowsDemo01.java:10)
at throwsdemo.ThrowsDemo01.main(ThrowsDemo01.java:6)
13.自定義異常:
(1)建立自定義異常:繼承自Exception 。習慣上包裝一下父類的構造方法。
格式:
public class MyException extends Exception {
public MyException() {
super();
}
public MyException(String msg) {
super(msg);
}
}
(2)使用自定義異常:
格式:
public String[] createArray(int length) throws MyException {
if (length < 0) {
throw new MyException("數組長度小於0,不合法");
}
return new String[length];
}
例1(以上述自定義異常和使用自定義異常爲例):
自定義異常類(繼承父類Exception):
package throwexception;
public class DivideByMinusException extends Exception{
public DivideByMinusException(){
super();
}
public DivideByMinusException(String message){
super(message);
}
}
測試自定義異常類:
package throwexception;
public class ThrowExceptionDemo {
public static void main(String[] args) {
try {
int result=divide(55,-5);
System.out.println("計算結果爲:"+result);
} catch (DivideByMinusException e) {
System.out.println(e.getMessage());
}
}
public static int divide(int x,int y) throws DivideByMinusException{
if(y<0){
throw new DivideByMinusException("被除數是負數~~~");
}
int result=x/y;
return result;
}
}
運行結果爲:
被除數是負數~~~
例2(以貨船載貨爲例自定義異常):
自定義LoadException異常:
package boat;
public class LoadException extends Exception{
public LoadException(){
super();
}
public LoadException(String message){
super(message);
}
}
貨船模擬裝貨類:
package boat;
public class Boat {
private static final int MAX_STORE=1000;
private int currentStore;
public void load(int num) throws LoadException{
System.out.println("貨船裝貨前當前載貨量:"+currentStore);
currentStore+=currentStore;//模擬裝貨
System.out.println("貨船裝貨後的當前載貨量:"+currentStore);
if(currentStore>MAX_STORE){
System.out.println("已超載,貨船面臨乘船危險~~");
}
}
}
測試貨船裝貨類:
package boat;
import java.util.Scanner;
public class TestBoat {
public static void main(String[] args) {
Boat bo=new Boat();
while(true){
Scanner scan=new Scanner(System.in);
System.out.print("請輸入要載入載貨量:");
int cur=scan.nextInt();
try {
bo.load(cur);
} catch (LoadException e) {
System.out.println("輸出 捕獲的異常:"+e.getMessage());
break;
}
scan.close();
}
}
}
*小結(finally易錯點):
例:
package easyeorror;
public class FinallyDemo {
public static void main(String[] args) {
int result=divide(4,6);
System.out.println("所返回 的結果是:"+result);
}
public static int divide(int x,int y){
try {
int temp=x+y;
return temp;
} catch (Exception e) {
System.out.println("發生異常了~~~~~~~");
}finally{
int result=x*y;
return result;
}
}
}
運行結果爲:
所返回 的結果是:24
【本次總結完畢】
2018.1.12