05 常用對象API
By Kevin Song
- 05-01 String類
- 05-02 基本數據類型對象包裝類
- 05-03 集合框架
- 05-03-01 Collection概述
- 05-03-02 List集合
- 05-03-03 Set集合
- 05-03-04 泛型
- 05-03-05 Map集合
- 05-03-06 工具類(Collections,Arrays)
- 05-03-07 JDK1.5 新特性
- 05-04 其他對象API
- 05-04-01 System類
- 05-04-02 Runtime類
- 05-04-03 Math類
- 05-04-04 Date類
- 05-04-05 Calendar類
05-01 String類
String類特點
特點1:字符串一旦初始化就不可以被改變
特點2:
s0字符串創建在常量池中
s1字符串直接在常量池中找abc
s0==s1輸出爲true因爲是同一個abc
String s0 = "abc";//“abc”存在字符串常量池中
String s1 = "abc";//在字符串常量池中找abc
s0==s1;//輸出爲true,因爲指向同一個abc
特點3:
s0字符串創建在常量池中
s1指向堆內存中的字符串對象
s0==s1輸出爲false因爲內存地址不一樣
s0.equals(s1)輸出爲true因爲比較的是字符串內容,都是abc所以爲true
String s0 = "abc";//“abc”存在字符串常量池中
String s1 = new String("abc");//新建一個字符串對象
s0==s1;//輸出爲false,因爲地址不一樣
s0.equals(s1);//輸出爲true,String類中的equals()重寫了Object中的equals,比較字符串內容而不是地址值
String類構造方法
構造方法一
String(byte[] bytes)
作用:將一個字節數組變成字符串
byte[] arr = {65,66,67,68};
String s = new String(arr);
System.out.println(s);
//輸出ABCD
構造方法二
String(char[] value)
String(char[] value, int offset, int count)
作用:將一個字符數組變成字符串
char[] arr = {G,r,e,a, t};
String s0 = new String(arr);
System.out.println(s0);
//輸出Great
String s1 = new String(arr, 2, 3);
System.out.println(s1);
//輸出eat
String類常見功能
- 獲取
- 獲取字符串中字符的個數(長度)
- int length();
- 根據位置獲取字符
- char charAt(int index);
- 根據字符\字符串獲取位置
- 從前向後找
- int indexOf(int ch); 獲取字符第一次出現的位置
- int indexOf(int ch, int fromIndex) 從指定位置進行對字符第一次出現位置的查找
- int indexOf(String str); 獲取字符串第一次出現的位置,找不到則爲-1
- int indexOf(String str, int fromIndex); 從指定位置進行對字符串第一次出現位置的查找
- 從後向前找
- int lastIndexOf(int ch); 獲取字符最後一次出現的位置
- int lastIndexOf(int ch, int fromIndex) 從指定位置進行對字符最後一次出現位置的查找
- int lastIndexOf(String str); 獲取字符串最後一次出現的位置
- int lastIndexOf(String str, int fromIndex); 從指定位置進行對字符串最後一次出現位置的查找
- 從前向後找
- 獲取字符串中的一部分字符串,也叫子串
- String substring(int beginIndex, int endIndex) 獲取字符串從beginIndex到endIndex-1位置的字串
- String substring(int beginIndex) 獲取字符串從beginIndex開始到結尾的字串
- 獲取字符串中字符的個數(長度)
- 轉換
- 將字符串轉換成字符串數組(字符串的切割)
- String[] split(String regex)
- 將字符串轉換成字符數組
- char [] toCharArray()
- 將字符串轉換成字節數組
- byte[] getBytes()
- 將字符串轉換成大寫小寫
- String toUpperCase() 大寫
- String toLowerCase() 小寫
- 將字符串中的指定內容替換
- String replace(char oldChar, char newChar) 用newChar替換所有oldChar
- String replace(String s1, string s2) 用s2替換所有s1
- 將字符串兩端的空格去除
- String trim()
- 將字符串進行連接
- String concat(string)
- 將字符串轉換成字符串數組(字符串的切割)
String s = "One, Two, Three";
String [] arr = s.split(",");//用","切割原字符串
Char [] chs = s.toCharArray();
- 將字符串轉換成字符:toCharArray() 方法
將字符轉換成字符串: String(char[] value) 構造方法
- 判斷
- 判斷兩個字符串內容是否相同
- boolean equals(Object obj)
- boolean equalsIgnoreCase(String anotherString) 忽略大小寫比較字符串內容
- 判斷字符串中是否包含指定字符串
- boolean contains(string str)
- 判斷字符串是否以指定字符串開頭或結尾
- boolean startsWith(string) 開頭
- boolean endsWith(string) 開頭
- 比較 比較基於字符串中各個字符的Unicode值
- int compareTo(String anotherString) 比較基於字符串中各個字符的Unicode值
- 如果此字符串等於參數字符串,則返回0
- 如果此字符串小於參數字符串,則返回負數
- 如果此字符串大於參數字符串,則返回正數
- intern()方法
- inter()方法:對字符串池進行操作
- 判斷
String s0 = new String(“abc”);
String s1 = s0.intern();//獲取字符串池中的數據
s0==s1;//false
String類練習
練習一
給定一個字符串數組,按照字典順序進行從小到大的排序
{“nba”,“abc”,“cba”,“zz”,“qq”,“haha”}
public class StringTest_1 {
public static void main(String[] args) {
printArray(arr);
sortString(arr);
printArray(arr);
}
public static void sortString(String[] arr) {
for(int i = 0; i < arr.length - 1; i++) {
for(int j = i + 1; j < arr.length; j++) {
if(arr[i].compareTo(arr[j])) //字符串比較用compareTo方法完成
swap(arr,i,j);
}
}
}
private static void swap(String[] arr, int i, int j) {
String temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void printArray(String[] arr) {
Syetem.out.println("[");
for(int i = 0; i < arr.length - 1; i++) {
if(i !=arr.length - 1)
System.out.print(arr[i] + ", ");
}
}
}
練習二
一個子串在整串中出現的次數
“nbagrwnbaxxznbaedqenba”
思路:
- 判斷要找的子串是否存在,如果存在,用indexOf獲取其出現位置
- 如果找到了,記錄出現的位置並在剩餘的字符串中繼續查找該子串,剩餘字符串的起始位置是出現位置+子串長度
- 通過循環完成查找,如果找不到就是-1,並且每次找到用計數器記錄
public class StringTest_2 {
public static void main(String[] args) {
String str = "nbagrwnbaxxznbaedqenba";
String key = "nba";
int count = getKeyStringCount(str,key);
System.out.println("count="+count);
}
public static int getKeyStringCount(String str, String key) {
//定義計數器
int ciount = 0;
//定義變量記錄key出現的位置
int index = 0;
while((index =str.indexOf(key, index))!=-1) {
index = index + key.length();
count++;
}
return count;
}
}
練習三
最大相同子串
qwerabcdtyuiop
xcabcdvbn
思路:
- 先看短字符串是否是長字符串的子串,如果是,那麼短的就是最大子串
- 如果短的不是最大子串,那就讓子串長度遞減,去繼續判斷
public class StringTest_3 {
public static void main(String[] args) {
String s1 = "qwerabcdtyuiop";
String s2 = "xcabcdvbn";
String s =getMaxSubstring(s1, s2);
System.out.println("s="+s);
}
public static String getMaxSubstring(String s1, String s2) {
for(int i = 0; i < s2.length(); i++) {
for(int a = 0, b = s2.length() - i; b != s2.length + 1; a++, b++) {
String sub = s2.substring(a, b);
if(s1.contacins(sub))
return sub;
}
}
}
}
StringBuffer類
StringBuffer:字符串緩衝區,用於存儲數據的容器
特點
- 長度是可變的
- 可以存儲不同類型的數據
- 最終轉換成字符串進行輸出
功能
- 添加
- StringBuffer append(data) 尾部添加
- StringBuffer insert(index, data) 在指定位置添加
- 刪除
- StringBuffer delete(start, end) 刪除start到end-1的字符串
- StringBuffer deleteCharAt(int index) 刪除指定位置的元素
- 查找
- char charAt(index)
- int indexOf(string)
- int lastIndexOf(srting)
- 修改
- StringBuffer replace(start, end, string)
- void setCharAt(index, char);
public static void bufferMethodDemo() {
StringBuffer sb = new String Buffer();
StringBuffer s1 = sb.append(4);
System.out.println(sb); //4
System.out.println(s1); //4
System.out.println(s1==sb); //true
}
StringBuilder類
- StringBuilder:線程不同步,用於單線程
- StringBuffer:線程同步,用於多線程
練習
將一個int數組變成字符串
public static String arrayToString(int[] arr) {
StringBuilder sb = new StringBuilder();
sb.append("[");
for(int i = 0; i < arr.length; i++) {
if(i != arr.length-1)
sb.append(arr[i] + ",");
else
sb.append(arr[i] + "]");
}
return sb.toString();
}
05-02 基本數據類型對象包裝類
概述
目的:爲了方便操作基本數據類型值,將其封裝成對象,在對象中定義了屬性和行爲,豐富了該數據的操作。用於描述該對象的類就稱爲基本數據類型對象包裝類
- Byte
- Short
- Integer
- Long
- Float
- Double
- Character
- Boolean
字符串和基本數值互相轉換
Integer類的字符串轉換成基本數值
public static int parseInt(String s)方法
Integer.parseInt("123"+1); //124
基本類型轉字符串
- 方法1:基本類型數值+“”
- 方法2:用String類中的靜態方法valueOf(基本類型數值);
- 方法3:用Integer的靜態方法valueOf(基本類型數值);
字符串轉基本類型
- 方法1:使用包裝類中的靜態方法 xxx parseXxx(“xxx類型的字符串”)
- int parseInt(“intstring”);
- int parseByte(“bytestring”);
- int parseShort(“shortstring”);
- int parseLong(“longstring”);
- int parseFloat(“floatstring”);
- int parseDouble(“doublestring”);
- int parseBoolean(“booleanstring”);
- int parseInt(“intstring”)
- 沒有parseChar
- 方法2:使用非靜態方法 intValue(), 將一個Integer對象轉換成基本數據類型值
進制轉換
十進制 –> 其他進制
- toBinaryString(DecNum);
- toOctalString(DecNum);
- toHexString(DecNum);
- toString(DecNum, 需要轉的進制)
System.out.println(Integer.toBinaryString(60));
System.out.println(Integer.toOctalString(60));
System.out.println(Integer.toHexString(60));
System.out.println(Integer.toString(60,4));//把十進制的60轉換成4進制的數
其他進制 –> 十進制
System.out.println(Integer.parseInt("110",2))把二進制的110轉換成10進制
JDK 1.5自動裝箱拆箱
Integer i = 4; //i = new Integer(4); 自動裝箱 簡化書寫
i = i + 6; // i = new Integer(i.intValue() + 6); i.intValue() 自動拆箱
Integer a = new Integer(127);
Integer b = new Integer(127);
a==b false
a.equals(b) true
自動裝箱如果裝的是一個字節,那麼該數據會被共享而不是重新開闢空間,
Integer x = 127; //如果是128那麼x==y是false
Integer y = 127;
x==y; true
x.equals(y); true
05-03 集合框架
05-03-01 Collection概述
集合定義:集合是用於存儲對象的容器
集合特點
- 用於儲存對象的容器
- 集合的長度是可變的
- 集合中不可以存儲基本數據類型值
集合框架定義:集合容器因爲內部的數據結構不同,有多種具體容器,不斷向上抽取,形成了集合框架。
- Collection
- List
- Vector
- ArrayList
- LinkedList
- Set:
- HashSet
- TreeSet
- List
集合使用技巧
- 是否需要唯一
- 需要:Set
- 有序:TreeSet(Comparable,Comparator)
- 無序:HashSet(hashCode(), equals())
- 和存儲順序一致(有序):LinkedHashSet
- 不需要:List
- 增刪快,查詢慢:LinkedList
- 增刪慢,查詢快:ArrayList
- 需要:Set
後綴名就是該集合所屬的體系
前綴名就是該集合的數據結構
框架的頂層Collection接口的常見方法
- 添加
- boolean add(Object obj)
- boolean addAll(Collection coll)
- 刪除
- boolean remove(Object obj)
- boolean removeAll(Collection coll)
- void clear()
- 判斷
- boolean contains(object obj)
- boolean containsAll(Collection coll)
- boolean isEmpty() 如果沒有元素,返回true
- 獲取
- int size()
- Iterator iterator(); 取出元素的方式,迭代器,該對象必須依賴於具體容器,因爲每一個容器的數據結構都不同,所以該迭代器對象是在容器中進行內部實現的。
- 其他
- boolean retainAll(Collection coll) 取交集
- Object[] toArray(); 將集合轉成數組
方法演示
public class CollectionDemo {
public static void main(String[] args) {
Collection coll new ArrayList();
show(coll);
}
public static void show(Collection coll) {
//添加元素 add()
coll.add("abc1");
coll.add("abc2");
coll.add("abc3");
//刪除元素 remove()
coll.remove("abc2") //會改變集合的長度
System.out.println(coll);
}
}
迭代器
迭代器原理 :迭代器就是一個實現了Iterator接口的每一個容器內部的內部對象
迭代器演示
import java.util.ArrayList;
import java.util.Collection;
public class IteratorDemo {
public static void main(String[] args) {
Collection coll = new ArrayList();
coll.add("abc1");
coll.add("abc2");
coll.add("abc3");
coll.add("abc4");
//使用了Collection中的iterator()方法,調用集合中的迭代器方法,是爲了獲取集合中的迭代器對象
Iterator it = coll.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
for(Iterator it = coll.iterator(); it.hasNext();) {
System.out.println(it.next());
}
}
}
05-03-02 List集合
List和Set特點
- Collection
- List
- 有序(存入和取出的順序一致)
- 元素都有索引(角標)
- 元素可以重複
- Set:
- 無序
- 元素不能重複
- List
特有的常見方法
- 添加
- void add(index, element)
- void add(index, collection)
- 刪除
- Object remove(index)
- 修改
- Object set(index, element)
- 獲取
- Object get(index)
- int idexOf(Object)
- int lastIndexOf(object)
- List sublist(from, to) 包含頭不包含尾
public class ListDemo {
public static void main(String[] args) {
List list = new ArrayList();
show(list);
}
public static void show(List list) {
//添加元素
list.add("abc1");
list.add("abc2");
list.add("abc3");
System.out.println(list); //[abc1, abc2, abc3]
//插入元素
list.add(1, "abc9");
//刪除元素
System.out.println(list.remove(2));
//修改元素
System.out.println(list.set(1, "abc8"));
//Iterator獲取
Iterator it = list.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
}
List中的迭代器
迭代器操作集合中的元素時,集合不可以操作,否則迭代器報錯 ConcurrentModificationException
Iterator it = list.iterator();
while(it.hasNext()) {
Object obj = it.next(); //java.util.ConcurrentModificationException
if(obj.equals("abc2")) {
list.add("abc9");//集合不可以再操作元素
} else
System.out.println(obj);
}
System.out.println(list);
解決方法:Iterator接口的子接口ListIterator來完成在迭代中對元素進行更多的操作。
可以在迭代過程中完成對元素的增刪改查
ListIterator it = list.listIterator(); //獲取列表迭代器對象
while(it.hasNext()) {
Object obj = it.next();
if(obj.equals("abc2")) {
it.add("abc9");
}
}
List中的子類對象
- Vector:內部是數組數據結構,是同步的,增刪,查詢都很慢
- ArrayList:內部是數組數據結構,是不同步的,代替Vector。查詢速度快
- LinkedList:內部是鏈表數據結構,是不同步的,增刪元素的速度很快
Vector演示
Vector v = new Vector();
v.addElement("abc1");
v.addElement("abc2");
v.addElement("abc3");
v.addElement("abc4");
Iterator it = v.Iterator;
while(it.hasNext()) {
System.out.println(it.next());
}
LinkedList演示
- 添加
- addFirst(); 在前面添加
- addLast(); 在後面添加
- 移除
- removeFirst(); 移除第一個元素,如果鏈表爲空,拋出NoSuchElementException
- removeLast(); 移除最後一個元素
- JDK 1.6 以後
- pollFirst(); 如果鏈表爲空,返回null
- pollLast();
- 獲取
- getFirst(); 獲取第一個元素,如果鏈表爲空,拋出NoSuchElementException
- getLast();
- JDK 1.6 以後
- peekFirst(); 如果鏈表爲空,返回null
- peekLast();
LinkedList link = new LinkedList();
link.addFirst("abc1");
link.addFirst("abc2");
link.addFirst("abc3");
link.addFirst("abc4");
System.out.println(link.getFirst());//獲取第一個但不刪除
System.out.println(link.removeFirst());//獲取第一個並且刪除
Iterator it = link.Iterator;
while(it.hasNext()) {
System.out.println(it.next());//輸出4321因爲addFirst是加在前面
}
LinkedList練習
- 堆棧數據結構:先進後出 First In Last Out FILO
- addFirst()
- removeFirst()
- 隊列數據結構:先進先出 First In First Out FIFO
- addLast()
- removeFirst()
ArrayList集合儲存自定對象
public class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
void int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class ArrayListTest {
public static void main(String[] args) {
ArrayList a1 = new ArrayList();
a1.add(new Person("Kevin",24));
a1.add(new Person("Steve",25));
a1.add(new Person("Tony",26));
a1.add(new Person("Peter",29));
Iterator it = a1.iterator();
while(it.hasNext()) {
//System.out.println((Person)it.next().getName());
Person p = (Person) it.next();//把
System.out.println(p.getName()+"-"+p.getAge());
}
}
}
05-03-03 Set集合
set接口中的方法和collection一致
- HashSet:內部數據結構是哈希表,無序,不重複,不同步
- LinkedHashSet
- TreeSet:可以對Set集合中的元素進行排序,是不同步的
HashSet集合
public class HashSetDemo {
public static void main(String[] args) {
HashSet hs = new HashSet();
hs.add("aaa");
hs.add("bbb");
hs.add("ccc");
hs.add("ccc");
Iterator it = hs.iterator();
while(it.hasNext()) {
System.out.println(it.next());//輸出是無序的,而且沒有重複的ccc
}
}
}
哈希表
把一個數據經過哈希算法,存在一個位置,查找時直接把新數據經過哈希算法找到數據所在位置,速度很快,哎就很舒服
HashSet保證該集合元素唯一性的方式
通過hashCode和equals方法來完成對象唯一性判斷
- 對象的hashCode值不同,不用判斷equals方法,直接存儲到哈希表
- 對象的hashCode值相同,判斷對象的equals方法是否爲true
- 如果爲true,則視爲相同元素,不存
- 如果爲false,則視爲不同元素,進行存儲
注意:如果元素要存儲到HashSet集合中,必須覆蓋HashCode方法和equals方法。如果定義類會產生很多對象,比如人,學生,書,通常都需要覆蓋equals, hashCode方法,建立對象判斷是否相同的依據
HashSet存儲自定義對象
public class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
return age;
}
public boolean equals(Object obj) {
Person p = (Person)obj;
return this.name.equals(p.name) && this.age == p.age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
void int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class HashSetTest {
public static void main(String[] args) {
HashSet hs = new HashSet();
hs.add(new Person("Kevin",24));
hs.add(new Person("Kevin",24));
hs.add(new Person("Steve",25));
hs.add(new Person("Tony",26));
hs.add(new Person("Peter",23));
Iterator it = hs.iterator();
while(it.hasNext()) {
Person p = (Person)it.next();
System.out.println(p.getName()+"..."+p.getAge());
}
}
}
集合框架練習
定義功能去除ArrayList中的重複元素
public class HashSetTest {
public static void main(String[] args) {
ArrayList a1 = new ArrayList();
a1.add("abc1");
a1.add("abc2");
a1.add("abc2");
a1.add("abc1");
a1.add("abc");
System.out.println(a1); //[abc, abc2, abc2, abc1, abc]
a1 = getSingleElement(a1);
System.out.println(a1); //[abc1, abc2, abc]
}
}
public static ArrayList getSingleElement(ArrayList al) {
//定義一個臨時容器
ArrayList temp = new ArrayList();
//迭代a1集合
Iterator it = a1.iterator();
while(it.hasNext()) {
Object obj = it.next();
//判斷被迭代到的元素是否在臨時容器存在
if(!temp.contains(obj)) {
temp.add(obj);
}
}
return temp;
}
}
LinkedHashSet
有序的HashSet
HashSet hs = new LinkedHashSet();
hs.add("a");
hs.add("b");
hs.add("c");
hs.add("d");
hs.add("e");
Iterator it = hs.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
TreeSet集合
可以對Set集合中的元素進行排序,是不同步的
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet ts = new TreeSet();
ts.add("aaa");
ts.add("bbb");
ts.add("zzz");
ts.add("ccc");
Iterator it = hs.iterator();
while(it.hasNext()) {
System.out.println(it.next());//按照元素字典順序排序
}
}
}
- TreeSet保證該集合元素唯一性的方式
- 比較方法的返回結果是否是0,是0就是相同元素,不存。
- TreeSet對元素進行排序的方式
- 方式一:按照自然順序排序
- 讓元素自身具備比較功能,需要實現Comparable接口,重寫compareTo()方法
- 方式二:不按照自然順序排序
- 讓集合自身具備比較功能,定義一個類實現Comparator接口,重寫compare()方法。將該類對象作爲參數傳遞給TreeSet集合的構造方法
- 方式一:按照自然順序排序
TreeSet存儲自定義對象
排序方式一
public class Person implements Comparable {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public int compareTo(Object o) {
Person p = (Person)o;
//比較年齡
int temp = this.age - p.age;
return temp == 0?this.name.compareTo(p.name):temp;//如果年齡相等,則比較名字,否則直接存入
//比較名字
int temp = this.name.compareTo(p.name);
return temp ==0?this.age - p.age:temp;//如果名字一樣,則比較年齡,否則直接存入
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
void int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class TreeSetTest {
public static void main(String[] args) {
TreeSet ts = new TreeSet(new ComparatorByName());//排序方式二
hs.add(new Person("Kevin",24));
hs.add(new Person("Kevin",24));
hs.add(new Person("Steve",25));
hs.add(new Person("Tony",26));
hs.add(new Person("Peter",23));
Iterator it = hs.iterator();
while(it.hasNext()) {
Person p = (Person)it.next();
System.out.println(p.getName()+":"+p.getAge());
}
}
}
排序方式二
- 定義一個比較器類,實現Comparator接口
- 重寫Comparator接口中的compare() 方法
- 把傳進來的Object類對象轉型成需要比較的對象
- 創建一個存儲compareTo() 方法結果的變量
- 如果先比較名字,則用p1.getName().compareTo(p2.getName())
- 如果先比較年齡,則用p1.getAge() - p2.getAge()
- 把這個類的對象傳給TreeSet類的構造方法
//創建一個根據Person類的name進行排序的比較器
public class ComparatorByName implements Comparator {
@Override
public int compare(Object o1, Object o2) {
//把傳進來的兩個對象轉換成Person類纔可以調用getAge()方法
Person p1 = (Person)o1;
Person p2 = (Person)o2;
int temp = p1.getName().compareTo(P2.getName());
return temp==0?p1.getAge() - p2.getAge():temp;
}
}
比較器應用
//把字符串按長度排序
public class TreeSetTest {
public static void main(String[] args) {
TreeSet ts = new TreeSet(new ComparatorByLength());
ts.add("cccc");
ts.add("aaa");
ts.add("bbbbb");
ts.add("abc");
ts.add("dddddd");
Iterator it = ts.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
}
public class ComparatorByLength implements Comparator {
@Override
public int compare(object o1, object o2) {
String s1 = (String)obj;
String s2 = (String)obj;
int temp = s1.Length() - s2.Length;
return temp==0?s1.compareTo(s2):temp;//這裏的compareTo是String類裏的方法
}
}
05-03-04 泛型
泛型概述
JDK1.5出現的安全機制
優點
- 將運行時期的問題ClassCastException轉到了編譯時期
- 不需要強制轉換
格式<>
當操作的引用數據類型不確定的時候,就用<>將要操作的引用數據類型傳入即可
ArrayList<String> a1 = new ArrayList<String>();
a1.add("abc");
a1.add("hahaha");
Iterator<String> it = a1.iterator();
while(it.hasNext()) {
//String str = (String)it.next();不需要強轉
String str = it.next();
System.out.println(str);
}
泛型技術是給編譯器使用的技術,用於編譯時期,確保了類型的安全
泛型擦除:運行時,會將泛型去掉,生成的class文件中是不帶泛型的
泛型補償:運行時,通過獲取元素的類型,進行轉換動作,不用使用者再強制轉換了
ArrayList<E>
ArrayList<String> a = new ArrayList<String>();
Tools<E1, E2, E3, E4>
Tools<Tinjing, Lvdian, Restaurant, Movie> a = new Tools<Tinjing, Lvdian, Restaurant, Movie>();
泛型在集合中的應用
public class GenericDemo {
public static void main(String[] args) {
TreeSet<Person> ts = new TreeSet<Person>(new ComparatorByName());
ts.add(new Person("Kevin", 24));
ts.add(new Person("Tony", 21));
ts.add(new Person("Steve", 26));
ts.add(new Person("Peter", 19));
}
Iterator<Person> it = ts.iterator();
while(it.hasNext()) {
Person p = (Person)it.next();
System.out.println(p);
}
}
public class ComparatorByName implements Comparator<Person> {
public int compare(Person o1, Person o2) {
int temp = o1.getName().compareTo(o2.getName());
return temp==0?o1.getAge() - o2.getAge():temp;
}
}
泛型類
JDK1.5以後,使用泛型來接收類中要操作的引用數據類型
泛型類:當類中操作的引用數據類型不確定的時候,就用泛型來表示
public class Tool<T> {
private T t;
public T getObject() {
return t;
}
public void setObject(T object) {
this.t = object;
}
}
public class GenericDefineDemo {
public static void main(String[] args) {
Tool<Student> tool = new Tool<Student>();
//只能傳Student。如果傳Worker無法通過編譯
tool.setObject(new Student());
Studengt stu = tool.getObject();
}
}
如果不使用泛型
- setObject傳入Worker時會編譯錯誤
- stu需要強制轉換成Student
public class GenericDefineDemo {
public static void main(String[] args) {
Tool tool = new Tool();
tool.setObject(new Student());
Studengt stu = (Student)tool.getObject();
}
}
泛型方法
- public void print(T str) {}
- print能處理的數據根據對象的泛型來定
- public void show(A str) {}
- show能處理的數據自定義爲A類型
泛型定義在方法上
修飾符 <A> 返回值類型 方法名() {}
注意:靜態方法只能將泛型定義在方法上
public class Tool<T> {
//把泛型定義在方法上
public <W> void show(W str) { //show的泛型在方法上自定義
System.out.println("show:"+str.toString());
}
public void print(T str) {//print的泛型跟着對象走
System.out.println("print:"+str);
}
//當方法靜態時,不能訪問類上定義的泛型。
public static void method(T obj) {
System.out.println("method:"+ obj);
}
//當方法靜態時,只能將泛型定義在方法上
public static <Y> void method(Y obj) {
System.out.println("method:" + obj);
}
}
public class GenericDemo {
public static void main(String[] args) {
Tool<String> tool = new Tool<String>();
//非靜態
tool.show(new Integer(4));
tool.show("abc");
tool.print("haha");
tool.print(new Integer(6));//報錯,因爲print的泛型跟着對象走只能處理String類型的參數
//靜態
tool.method(new Integer(8));
tool.method("abcd");
}
}
泛型接口
把泛型定義在接口上
interface Inter<A> {
public void show(A a);
}
//實現Inter時知道類型
class InterImp1 implements Inter<String> {
public void show(String str) {
System.out.println("show:"+ str)
}
}
//實現Inter時不知道類型
class InterImp2<B> implements Inter<B> {
public void show(B b) {
System.out.println("show:"+b);
}
}
public class GenericDemo {
public static void main(String[] args) {
InterImp1 in1 = new InterImp();
in1.show("abc");
InterImp2<Integer> in2 = new InterImp2<Integer>();
in2.show(5);
}
}
泛型限定
類型的通配符
public class GenericDemo {
public static void main(String[] args) {
ArrayList<Teacher> a1 = new ArrayList<Teacher>();
a1.add("John", 32);
a1.add("Smith", 28);
ArrayList<Student> a2 = new ArrayList<Student>();
a2.add("Leo", 23);
s2.add("Kevin", 24);
printCollection(a1);
printCollection(a2);
}
public static void printCollection(Collection<? extends Person> a1) {
Iterator<? extends Person> it = a1.iterator();
while(it.hasNext()) {
System.out.println(it.next().toString());
}
}
}
05-03-05 Map集合
Map集合概述
Map和Collection區別
- Map(雙列集合) 一次添加一對元素
- Collection(單列集合) 一次添加一個元素
Map集合中必須保證Key的唯一性
Map集合常用方法
- 添加
- V put(key, value) 返回前一個和key關聯的值,如果沒有返回null
- 刪除
- void clear() 清空map集合
- V remove (key) 根據指定的key刪除鍵值對
- 判斷
- boolean containsKey(key)
- boolean containsValue(value)
- boolean isEmpty()
- 獲取
- V get(key) 通過鍵獲取值,如果沒有該鍵,返回null
- int size() 獲取鍵值對個數
public class MapDemo {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<Integer, String> ();
method(map);
}
//method_2獲取所有的value
public static void method_2(Map<Integer, String> map) {
map.put(1,"abc");
map.put(2,"cde");
map.put(3,"efg");
map.put(4,"ghi");
//獲取map中所有Key所在的set集合
Set<Integer> keySet = map.keySet();
//用迭代器獲取每一個鍵
Iterator<Integer> it = keySet.iterator();
while(it.hasNext()) {
Integer key = it.next();
//通過key獲取值
String value = map.get(Key);
System.out.println(key+":"+value);
}
}
//method演示基本功能
public static void method(Map<Integer, String> map) {
//添加元素(相同Key,值會覆蓋)
System.out.println(map.put(24, "Kevin"));//輸出null
System.out.println(map.put(24, "Leo"));//輸出Leo
map.put(20, "Peter");
map.put(29, "Tony");
//刪除
map.remove(20);//Peter被刪
//判斷
map.containsKey(24);//true
//獲取
map.get(29);//Tony
}
}
取出Value方式一
- 用keySet()方法獲取Key所在的Set集合
- 用迭代器獲取每一個Key
- 通過map.get(Key)獲取Value
//獲取map中所有Key所在的set集合
Set<Integer> keySet = map.keySet();
//用迭代器獲取每一個鍵
Iterator<Integer> it = keySet.iterator();
while(it.hasNext()) {
Integer key = it.next();
//通過key獲取值
String value = map.get(Key);
System.out.println(key+":"+value);
}
取出Value方式二
- entrySet()方法把Key和Value的映射關係作爲一個對象存儲到了set集合中
- 這個映射對象是Map.Entry類型,Entry是Map的內部接口
Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
Iterator<Map.Entry<Integer, String>> it = entrySet.iterator();
while(it.hasNext()) {
Map.Entry<Integer, String> me =it.next();
Integer key = me.getKey();
String value = me.getValue();
System.out.println(key+":"+value);
}
取出Value方式三
用Collection values()方法取出values值
Collection <String> values = map.values();
Iterator<String> it = values.iterator();
while(it2.hasNext()) {
System.out.println(it2.next());
}
Map集合常用子類對象
Map常用的子類
- Hashtable:內部結構是哈希表,是同步的,不允許null作爲Key或Value
- Properties類:用來存儲鍵值對型的配置文件信息
- HashMap:內部結構是哈希表,是不同步的,允許null作爲Key或Value
- TreeMap:內部結構是二叉樹,是不同步的,可以對Map中的Key**排序**
HashMap存儲自定義對象
將學生對象和學生的歸屬地通過Key和Value存儲到Map集合中
public class HashMapDemo {
public static void main(String[] args) {
HashMap<Student, String> hm = new HashMap<Student, String>();
hm.put(new Student("Kevin",24), "CN");
hm.put(new Student("Tony",32), "US");
hm.put(new Student("Seb",29),"RU");
//Set<Student> keySet = hm.keySet();
Iterator<Student> it = hm.keySet().iterator();
while(it.hasNext()) {
Student key = it.next();
String value = hm.get(key);
System.out.println(key.getName()+":"+key.getAge()+"-"+value);
}
}
}
TreeMap存儲自定義對象
public class TreeMapDemo {
public static void main(String[] args) {
TreeMap<Student, String> tm = new TreeMap<Student, String>();
hm.put(new Student("Kevin",24), "CN");
hm.put(new Student("Tony",32), "US");
hm.put(new Student("Seb",29),"RU");
Iterator<Map.Entry<Student, String>> it = tm.entrySet().iterator();
while(it.hasNext()) {
Map.Entry<Student, String> me = it.next();
Student key = me.getKey();
String value = me.getValue();
System.out.println(key.getName()+":"+key.getAge()+"-"+value);
}
}
LinkedHashMap
有序的HashMap
public class LinedHashMap {
public static void main(String[] args) {
HashMap<Integer,String> hm = new LinkedHashMap<Integer,String>();
hm.put(3,"KK");
hm.put(1,"AA");
hm.put(2,"LL");
Iterator<Map.Entry<Integer,String>> it = hm.entrySet().iterator();
while(it.hasNext()) {
Map.Entry<Integer,String> me = it.next();
Integer key = me.getKey();
String value = me.getValue();
System.out.println(key+":"+value);
}
}
}
Map集合練習
練習:”asdfdsadfa”獲取該字符串中每一個字母出現的次數
要求打印結果是:a(2)b(1)…;
思路:
- 字母和次數之間存在映射關係,而且無有序編號,所以用Map集合(有有序編號才用Array)
- 保證唯一性一方有順序如a,b,c。用TreeMap
- 把字符串轉換成字符數組
- 遍歷字符數組,用每一個字母作爲Key去查Map集合這個表
- 如果Key不存在,就將該子母Key作爲1存儲到map集合中
- 如果Key存在,就將該字母鍵對應值取出並+1,再存儲到Map集合中
public class MapTest {
public static void main(String[] args) {
String str = "asdfdsadfa";
String s = getCharCount(str);
System.out.println(s);
}
public static String getCharCount(String str) {
//將字符串變成字符數組
char[] chs = str.toCharArray();
//定義map集合表
Map<Character,Integer> map = new TreeMap<Character,Integer>();
for(int i = 0; i < chs.length; i++) {
//將數組中的字母作爲key去查map表
Integer value = map.get(chs[i]);
//判斷值是否爲null
/*
if(value == null) {
map.put(cha[i],1);
} else {
map.put(cha[i],value + 1)
}
*/
if(value!=null) {
count = value + 1;
]
map.put(chs[i],count);
}
return mapToString(map);
}
private static String mapToString(Map<Character, Integer> map) {
StringBuilder sb = new StringBuilder();
Iterator<Charater> it = map.keySet().iterator();
while(it.hasNext()) {
Character key = it.next();
Integer value = map.get(key);
sb.append(key+"("+value+")");
}
return sb;
}
}
05-03-06 工具類(Collections,Arrays)
Collections類
Collections類裏的方法都是靜態的
sort()方法
public static void demo_1() {
List<String> list = new ArrayList<String>();
list.add("bbb");
list.add("aaa");
list.add("ccc");
System.out.println(list);
//對list集合進行指定順序的排序
Collections.sort(list);
mySort(list);
System.out.println(list);
}
//自定泛型T,傳進來的List裏的元素必須是可以比較的所以extends Comparable,
//而Comparable<>也要定義泛型,只要是T或者T的子類都可以傳進來所以Comparable的泛型是<? super T>
public static <T extends Comparable<? super T>> void mySort(List<T> list) {
for(int i = 0; i < list.size() - 1; i++) {
for(int j = i + 1; j < list.size(); j ++) {
if(list.get(i).compareTo(list.get(j))>0) {
T temp = list.get(i);
listset(i, list.get(j));
list.set(j, temp);
}
}
}
}
binarySearch()方法
二分查找(折半查找)前必須先排序
int index = Collections.binarySearch(list, "abc");
max()方法
最大值
String max = Collections.max(list);
reverseOrder()逆序方法
逆向排序
TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder());
原理:
TreeSet<String> ts = new TreeSet<String>(new Comparator<String>()) {
@Override
public int compare(String o1, String o2) {
int temp = o2.comareTo(o1);
return temp;
}
}
replace()替換方法
Collections.replaceAll(list, "cba", "nba");//用nba替換cba
fill()全部替換方法
//全替換成cc
Collections.fill(list, "cc");
shuffle()隨機排序方法
Collections.shuffle(list)
synchronizedList()方法
返回一個同步list
原理:
//非同步的list
List list = new ArrayList();
//返回一個同步的list
list = MyCollections.synList(list);
class MyCollections {
public static List synList(List list) {
return new MyList(list);
}
}
class MyList {
private List list;
MyList(List list) {
this.list = list;
}
public boolean add(Object obj) {
synchronized(lock) {
return list.add(obj);
}
}
public boolean remove(Object obj) {
synchronized(lock) {
return list.remove(obj);
}
}
}
Arrays類
Arrays類裏的方法都是靜態的
toString()方法
public class ArraysDemo {
public static void main(String[] args) {
int[] arr = {3,1,5,6,3,6};
System.out.println(Arrays.toString(arr))
}
}
toString的實現方式
public static String myToString(int[] a) {
int iMax = a.length - 1;
if (iMax == -1)
return "[]";
StringBuilder b = new StringBuilder();
b.append('[');
for(int i = 0;; i++) { //中間省略判斷條件,默認true
b.append(a[i]);
if(i == iMax)
return b.append(']').toString();
b.append(", ");
}
}
Array和Collections相互轉換
數組轉成集合
Arrays類中的asList()方法
作用:可以使用集合的方法操作數組中的元素(比如contains())
注意:數組長度固定,所以對於集合的增刪方法是不可以使用的,否則會發生UnsupportedOperationException
public class ArraysDemo {
public static void main(String[] args) {
String[] arr = {"abc", "haha", "xixi"};
List<String> list = Arrays.asList(arr);
boolean b = list.contains("xixi");
System.out.println("b="+b);
}
}
- 如果數組中的元素是對象,那麼轉成集合時,直接將數組中的元素作爲集合中的元素進行存儲
- 如果數組中的元素是基本類型數值,那麼會將該數組作爲集合中的元素進行存儲
集合轉成數組
Collections接口中的toArray()方法
作用:可以對集合中的元素操作的方法進行限定,不允許對其進行增刪
toArray()方法需要傳入一個指定類型的數組
- 指定類型數組的長度如果小於集合的size,那麼該方法會創建一個同類型並和集合相同size的數組
- 指定類型數組的長度如果大於集合的size,那麼該方法會使用指定的數組,存儲集合中的元素,其他位置默認爲null
public class ToArray {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("abc1");
list.add("abc2");
list.add("abc3");
String[] arr = list.toArray(new String[list.size()]);
}
}
05-03-07 JDK1.5 新特性
ForEach循環
格式:
for(類型 變量:Collection集合|數組) {
Code;
}
遍歷集合
public class ForEachDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("abc1");
list.add("abc2");
list.add("abc3");
//傳統迭代遍歷
Iterator<String> it = list.iterator();
while(it.hasNext) {
System.out.println(it.next());
}
//foreach語句
for(String s : list) {
System.out.println(s);
}
}
}
遍歷數組
int[] arr = {3,1,5,7,4};
for(int i : arr) {
System.out.println(i);
}
For循環和ForEach的區別
- 傳統for可以完成對語句執行很多次,因爲可以定義控制循環的增量和條件
- 高級for是一種簡化形式,它必須有被遍歷的目標,該目標要麼是數組,要麼是Collection單列集合
Map集合必須轉換成單列set纔可以使用ForEach遍歷
Map<Integer,String> map = new HashMap<Integer,String>();
map.put(3,"a");
map.put(1,"b");
map.put(2,"c");
for(Integer key : map.keySet()) {
String value = map.get(key);
System.out.println(key+":"+value);
}
for(Map.Entry<Integer,String> me : map.entrySet()) {
Integer key = me.getKey();
String value = me.getValue();
System.out.println(key+":"+value);
}
方法可變參數
方法的可變參數:其實就是一個數組,但是接收的數組的元素,自動將這些元素封裝成數組,簡化了調用者的書寫
注意:可變參數類型,必須定義在參數列表的結尾
public class ParameterDemo {
public static void main(String[] args) {
int[] arr = {5,1,4,7,3};
int sum = add(arr);
int sum_new = newAdd(5,1,4,7,3);
System.out.println("sum_new="+sum_new);
}
//方法的可變參數
public static int newAdd(int... arr) {
int sum = 0;
for(int i = 0; i < arr.length; i++) {
sum = sum + arr[i];
}
return sum;
}
//參數列表接收一個數組
public static void add(int[] arr) {
int sum = 0;
for(int i = 0; i < arr.length; i++) {
sum = sum + arr[i];
}
return sum;
}
}
靜態導入
import static java.util.Collections.sort;
import static java.lang.System.*;
public class StaticImportDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("abc3");
list.add("abc1");
list.add("abc2");
out.println(list);
sort(list);
out.println(list);
}
}
05-04 其他對象API
05-04-01 System類
System類中的方法和屬性都是靜態的,所以不可以被實例化
常見方法
- long currentTimeMillis() 獲取當前時間到UTC 1970.1.1之間的毫秒值
long l1 = System.currentTimeMillis();
System.out.println(l1);
- Properties getProperties() 獲取系統的屬性,並儲存到Properties集合中
- Properties集合中存儲的都是String類型的Key和Value
- 最好使用Properties集合自己的儲存和取出方法來完成元素的操作
Property prop = System.getProperties();
Set<String> nameSet = prop.stringProperyNames();
for(String name : nameSet) {
String value = prop.getProperty(name);
System.out.println(name+":"+value);
}
- String getProperty() 獲取String類型的屬性
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
System.out.println("Hello"+LINE_SEPARATOR+"world");
- setProperty(“mykey”, “myvalue”) 給系統設置屬性信息
05-04-02 Runtime類
特點
- Runtime類沒有構造方法,說明該類不可以創建對象。
- Runtime類有非靜態的方法getRuntime(),說明該類提供靜態返回該類對象的方法,而且只有一個對象(單例設計模式)
Runtime r = Runtime.getRuntime();
- process exec() 方法:執行
//用notepad運行Runtime.txt
r.exec("notepad.exe c:\\Runtime.txt");
//打開QQ
r.exec("c:\\abc\\QQ.exe");
Process p = r.exec("notepad.exe c:\\Runtime.txt");
p.destroy();
05-04-03 Math類
Math類包含用於執行基本數學運算的方法,如初等指數、對數、平方根和三角函數。
常用方法
- ceil() 返回大於參數的最小整數
- floor() 返回小於參數的最大整數
- round() 返回四捨五入的整數
- pow(a,b) a的b次方
double d1 = Math.ceil(12.56);
double d2 = Math.floor(12.56);
double d3 = Math.round(12.56);
double d4 = Math.poe(10,2);
System.out.println("d1="+d1); 13.0
System.out.println("d2="+d2); 12.0
System.out.println("d3="+d3); 13.0
System.out.println("d4="+d4); 1000
隨機數生成
方法一:Math類,ramdom()方法
- ramdom() 返回0到1之間的隨機數,包括0
double d = Math.random();
方法二:Random類實例化對象
Random r = new Random();
int d = r.nextInt(10)
//返回1到10之間隨機的整數
05-04-04 Date類
構造方法
public class DateDemo {
public static void main(String[] args) {
long time = System.currentTimeMillis();
Date date1 = new Date();//當前日期和時間封裝成對象
Date date2 = new Date(time)//指定毫秒封裝成對象
}
}
日期對象和毫秒值之間的轉換
毫秒值 –> 日期對象
- 通過Date對象的構造方法new Date(timeMillis);
- setTime()設置
日期對象 –> 毫秒值
- getTime()獲取
日期對象的格式化
日期對象 –> 日期格式字符串
用DateFormat類中的format方法
Date date = new Date();
//獲取默認風格日期格式對象, FULL,LONG可以指定風格
DateFormat dateFormat = DateFormat.getDataInstance(DateFormat.FULL);
String str_date = dateFormat.format(date);
自定義風格的日期對象
Date date = new Date();
DateFormat dateFormat = new SimpleDateFormat("yyyy--MM--dd");
String str_date = dateFormat.format(date);
日期格式字符串 –> 日期對象
用DateFormat類中的parse方法
String str_date = "2017-6-20";
//獲取默認風格日期格式對象, FULL,LONG可以指定風格
DateFormat dateFormat = DateFormat.getDateInstance();
Date date = dateFormat.parse(str_date);
自定義風格的日期格式字符串
String str_date = "2017---6---20";
DateFormat dateFormat = new SimpleDateFormat("yyyy---MM---dd");
Date date = dateFormat.parse(str_date);
Date練習
2012-9-1到2017-6-20中間有多少天
思路:
- 將日期字符串轉換成日期對象
- 將Date對象轉換成毫秒值
- 相減再變成天數
public class DateTest {
public static void main(String[] args) {
String str_date1 = "2012-9-1";
String str_date2 = "2017-6-20";
compareDate(str_date1, str_date2);
}
public static void compareDate(String str_date1, String str_date2) {
//將日期字符串轉換成日期對象
DateFormat dateFormat = DateFormat.getDateInstance();
dateFormat = new SimpleDateFormat("yyyy--MM--dd");
Date date1 = dateFormat.Parse(str_date1);
Date date2 = dateFormat.Parse(str_date2);
//將Date對象轉換成毫秒值
long time1 = date1.getTime();
long time2 = date2.getTime();
long time = Math.abs(time1 - time2);
int day = getDay(time);
System.out.println(day);
}
private static int getDay(long time) {
int day = (int)(time/1000/60/60/24);
return day;
}
}
05-04-05 Calendar類
public class CalendarDemo {
public static void main(String[] args) {
Calendar c = Calendar.getInstance();
c.set(2011, 3, 10);//設置時間
c.add(Calendar.YEAR, 2)//加2年
showDate(c);
}
public static void showDate(Calendar c) {
Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH) + 1;
int day = c.get(Calendar.DAY_OF_MONTH);
int week = c.get(Calendar.DAY_OF_WEEK);
System.out.println(year+"年"+month+"月"+day+"日"+getWeek(weel));
}
public static void getWeek(int[] i) {
String[] weeks = {"", "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"}
returns weeks[i];
}
}