1、數組
數組屬于引用類型數據,實質也是對象
動態初始化
先定義,然后new分配空間,接著再初始化賦值,舉例:
int a[];
a = new int[3];
a[0] = 1;
a[1] = 2;
a[2] = 3;
靜態初始化
定義的時候就賦值,舉例:
int a[] = {1,2,3};
二維數組
定義舉例:
int[][] a = {{1,2},{3,4}};
int[][] b = new int[2][];
在表格等情況下可能會用到,舉例:
Object[] o1 = {"aaa", 18, "man"};
Object[] o2 = {"bbb", 22, "man"};
Object[] o3 = {"ccc", 20, "woman"};
Object[][] otable = new Object[3][];
otable[0] = o1;
otable[1] = o2;
otable[2] = o3;
for(Object[] o: otable)
System.out.println(Arrays.toString(o));
結果:
[aaa, 18, man]
[bbb, 22, man]
[ccc, 20, woman]
數組復制
使用System.arraycopy(原數組, 起始位置, 拷貝到的數組, 起始位置, 拷貝長度)
,舉例:
int[] a = {1,2,3,4,5};
int[] b = {0,0,0,0,0};
System.arraycopy(a, 1, b, 1, 3);
System.out.println(Arrays.toString(b)); //[0, 2, 3, 4, 0]
舉例:
String[] s = {"1", "2", "3"};
String[] p = new String[s.length];
System.arraycopy(s, 0, p, 0, s.length);
2、String
不可變類型序列,在java.lang
下的類,因此每個用""
包起來的都是String類的一個實例
charAt(index)
返回字符串第index個字符,舉例:
String s = "abcde";
System.out.print(s.charAt(2)); //c
length()
字符串長度
indexOf(str[,start])
返回字符串出現str的第一個位置(沒有返回-1),第二個可選參數代表開始索引位置,舉例:
String s = "abcde";
System.out.print(s.indexOf("c")); //2
equals(str)
對于是否與str字符序列相等
equalsIgnoreCase(str)
忽略大小寫后比較和str是否一樣,舉例:
String s = "abcde";
System.out.print(s.equalsIgnoreCase("ABCDE")); //true
replace(old, new)
替換單個字符,舉例:
String s = "abcde";
System.out.println(s.replace('a', 's')); //bbcde
replaceAll(old, new)
替換字符串,舉例:
String s = "abcde";
System.out.println(s.replaceAll("a", "bcd")); //bcdbcde
里面也可以通過匹配正則表達式來替換,舉例:
String a = "abc123de";
System.out.println(a.replaceAll("\\d+", "aaa")); //abcaaade
startsWith(str)/endsWith(str)
是否以str開頭/結尾
toUpperCase()/toLowerCase()
全部字符轉大寫/小寫
substring(startIndex[,endIndex])
返回從startIndex到結尾的子序列,第二個參數可選,為到endIndex的子序列
trim()
去掉開頭或者結尾空格后的字符串,相當于python的strip()
split(str)
按str分割字符串,舉例:
String s = "abcde ";
System.out.print(s.split("a")[1]); //bcde
實際上應該是按正則表達式來分割字符串,舉例:
System.out.println(Arrays.toString("sd2a3s".split("\\d"))); //[sd, a, s]
toCharArray()
轉成char
字符數組,舉例:
String a = "abcde";
for(char c: a.toCharArray())
System.err.println(c);
matches()
匹配正則表達式,符合則返回true
,否則返回false
,舉例:
String a = "abcde";
System.out.println(a.matches("[a-z]+")); //true
getChars()/getBytes()
獲得字符/字節數組
編碼解碼操作
使用getBytes(編碼)
進行編碼(需要拋出異常),使用String(byte, 編碼)
進行解碼,舉例:
public static void main(String[] args) throws Exception{
String s = "你好";
byte[] b = s.getBytes("utf-8");
System.out.println(new String(b, "utf-8")); //你好
}
要注意的是編碼和解碼時必須使用統一編碼,否則會造成亂碼,此時則需要再按其解碼的編碼進行編碼,然后再按正確的編碼進行解碼,舉例:
public static void main(String[] args) throws Exception{
String s = "你好";
byte[] b = s.getBytes("utf-8");
String s1 = new String(b, "gbk");
System.out.println(s1); //浣犲ソ
byte[] b1 = s1.getBytes("gbk");
String s2 = new String(b1, "utf-8");
System.out.println(s2); //你好
}
3、容器API
Java提供了一個容器接口Collection(需要import java.util.*;
),其下關系:
-Collection(接口)
-Set(接口)
-HashSet(類)
-List(接口)
-LinkedList(類)
-ArrayList(類)
-Map(接口)
-HashMap(類)
其中定義也有有講究的,比如:
Collection a = new ArrayList();
ArrayList a = new ArrayList();
上面兩者的區別:前者到時候如果想轉LinkedList時可以直接轉,而后者不行
3.1 Collection
其下的類都有以下的通用接口
add(Object)
添加元素(里面填的是對象),例如:a.add(new Integer(123))
size()
列表長度
remove(Object)
清除某個對象(里面也都是對象)
contains(Object)
是否包含該元素
iterator()
在這些數據類型下都有一個iterator接口,即迭代器,其定義了下面三個方法:
boolean hasNext(); //判斷游標右邊是否還有元素
Object next(); //返回游標右邊元素,并將游標往右移一位
void remove(); //刪除游標左邊的元素
實現了上面的方法后就可以使用迭代器了,舉例:
Collection c = new HashSet();
c.add(new String("1"));
c.add(new String("2"));
c.add(new String("3"));
Iterator i = c.iterator();
while(i.hashNext()){
String a = i.next();
}
上面可以用for語句實現:
Collection c = new HashSet();
c.add(new String("1"));
c.add(new String("2"));
c.add(new String("3"));
for(Object i: c)
System.out.println(i);
isEmpty()
是否為空
clear()
清空容器中所有元素
toArray()
轉化成Object數組
containsAll(Collection)
是否包含該容器的所有元素
addAll(Collection)
添加容器的所有元素
removeAll(Collection)
刪除本容器和該容器都包含的元素
retainAll(Collection)
取本容器和該容器中都包含的元素
3.2 List
列表里面可以存放各種類型的元素對象(注意是對象),有序,相比數組除了存放對象可以隨意外,其不像數組大小固定,可以動態擴容,但是速度比數組慢。在java.util.Collections
類下的List接口提供了常用方法如下
sort(List)
排序
reverse(List)
將原來的List倒過來,不是從大到小排序
shuffle(List)
隨機排序
binarySearch(List, Object)
二分查找,第二個參數是要查找的對象,結果返回對象下標
copy(List1, List2)
將List2內容拷到List1
3.2.1 ArrayList
底層是數組實現的列表,查詢效率高,增刪效率低,線程不安全
3.2.2 LinkedList
和ArrayList相比,主要區別就是底層是鏈表實現的,因此查詢效率低,增刪效率高,線程也不安全
3.2.3 Vector
底層是數組實現的鏈表,相關的方法都加了同步檢查(synchronized
標記),因此線程安全,但同時效率也會低一些,使用方法和前兩個差不多
3.2.4常用方法
add(index, Object)
重寫了方法,在第幾個位置插入元素
set(index, Object)
修改第幾個位置元素的值
get(index)
獲取第幾個位置元素的值
remove(index)
重寫了方法,刪除第幾個位置的元素
indexOf(Object)
獲取某個元素的下標(第一個),沒有就-1
lastIndexOf(Object)
獲取某個元素的下標(最后一個)
3.3 Map
Map接口提供了鍵值對存放的數據類型接口
3.3.1 HashMap
通過鍵值對標識,底層是由ArrayList+LinkedList結合而成的hash表(總體由多行ArrayList組成,每行內由LinkedList組成)實現,對于該數據結果判斷是否內容相等,一般不用equals,用hashCode
來比較
3.3.2 TreeMap
底層是通過紅黑二叉樹來實現,效率一般低于HashMap,但是在排序Map的時候則會用到,即會根據Key值排序存儲(底層繼承了Comparable
接口,實現的public int compareTo(Object obj){}
方法是由Key排序)
3.3.3 HashTable
相比HashMap線程更安全,但是效率低,而且key和value不允許為空
3.3.4 常用方法
put(Object key, Object value)
添加鍵值對,本來添加的鍵值都必須是對象,但是在java1.5以后Map下支持自動將基礎數據類型轉成對象和對象轉成基礎數據(自動打包/解包機制),所以可以直接放基礎數據,到時候會自動轉成對象,舉例:
Map m = new HashMap();
m.put("a", 1); //自動轉成String和Integer對象
int a = (Integer)m.get("a");
System.out.println(a)
get(Object key)
獲取鍵值對
keySet()
獲取所有鍵名,舉例循環輸出所有值:
Map<String, String> m = new HashMap<String, String>();
m.put("aaa", "bbb");
m.put("bbb", "ccc");
for (String s : m.keySet()) {
System.out.println(m.get(s));
}
entrySet()
獲取所有鍵值對的集合,返回的是Entry
對象,舉例:
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class test {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "aaa");
map.put(2, "bbb");
Set<Entry<Integer, String>> s = map.entrySet(); //返回Entry對象
for (Iterator<Entry<Integer, String>> iterator = s.iterator(); iterator
.hasNext();) {
Entry<Integer, String> entry = iterator.next();
System.out.println(entry.getKey() + ":" + entry.getValue());
}
}
}
用迭代器比較繁瑣,可以直接用for(x:XS)
方式輸出,舉例:
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "aaa");
map.put(2, "bbb");
for (Entry<Integer, String> m : map.entrySet()) {
System.out.println(m.getKey() + ":" + m.getValue());
}
}
values()
獲取所有值
remove(Object key)
containsKey(Object key)
是否包含鍵
containsValue(Object Value)
是否包含值
size()
putAll(Map)
添加所有鍵值對
clear()
清空鍵值對
3.4 Set
集合接口,無序(即無法用下標索引),不可重復
3.4.1 HashSet
底層是基于HashMap實現,相當于一個簡化版HashMap,因此查詢和增刪效率都較高,使用方法可以參考Collection
里的方法
3.4.2 TreeSet
底層是TreeMap實現的集合,所以結果會以從小到大排序
4、泛型
原來容器里的數據對象類型都是沒有限制,因此基本都是接受Object,為了能夠確定容器里存放的對象類型,引入了泛型,舉例:
List<String> li = new ArrayList<String>();
這樣所有的數據就都只能是String對象了,包括取數據時也可以使用泛型控制的迭代器,舉例:
for(Iterator<String> it = li.interator(); it.hasNext(); )
{
String s = it.next();
System.out.println(s);
}
至于何時可以使用泛型,可以參考Api文檔,當有<字符>
標識則說明可以使用,比如Map<K, V>
則說明鍵值都可以設置,所以就可以這樣寫:
Map<String, Integer> m = new hashMap<String, Integer>();
自定義泛型類
當自己寫的類里假如需要一個泛型容器時,可以通過<字符>
(一般用T
/E
/K
/V
/?
,分別代表type
/element
/key
/value
/不確定類型,但其實啥都可以)來定義,此時該字符相當于一個形參,當實例化時設置泛型類后,該字符就是什么類,舉例:
import java.util.Arrays;
public class test {
public static void main(String[] args) {
MyCollection<String> s = new MyCollection<String>(); // 設置了String的泛型,該對象里的T變成了String類
s.set("aaa", 0); // 第一個參數只能傳String
System.out.println(s.toString());
}
}
class MyCollection<T> { // 代表泛型類的形參
Object[] o = new Object[5];
public void set(T t, int index) { // T即傳入的泛型類
o[index] = t;
}
public String toString() {
return Arrays.toString(this.o);
}
}