(一)LinkedList類練習
操作索引值的方法是List接口特有的方法。
/*
定義一個LinkedList存儲一副撲克牌,再定義一個方法可以洗牌。
*/
class Poker{ //實體類
String number;//點數
String color;//顏色
public Poker(String number, String color) {
super();
this.number = number;
this.color = color;
}
@Override
public String toString() {
return "{點數:"+this.number+" 顏色:"+this.color+"}";
}
}
public class test2 {
public static void main(String[] args) {
LinkedList pokers=new LinkedList();
pokers=creatPoker();
//showPoker(pokers);
shufflePoker(pokers);
showPoker(pokers);
}
//生成一副撲克牌
public static LinkedList creatPoker() {
LinkedList list=new LinkedList();
//定義一個數組存儲所有的點數
String[] nums= {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
//定義一個數組存儲所有的花色
String[] colors= {"方塊","梅花","紅桃","黑桃"};
for(int i=0;i<nums.length;i++) {
for(int j=0;j<colors.length;j++) {
list.add(new Poker(nums[i],colors[j]));
}
}
return list;
}
public static void showPoker(LinkedList pokers) {//輸出牌的格式
for(int i=0;i<pokers.size();i++) {
System.out.print(pokers.get(i));
if(i%10==9)
System.out.println();
}
}
public static void shufflePoker(LinkedList pokers) {//洗牌,任意兩張牌交換位置
Random random=new Random();//生成隨機數
for(int i=0;i<100;i++) {//任意兩張牌交換,交換次數越多,越亂
//隨機產生兩個索引值
int index1=random.nextInt(pokers.size());
int index2=random.nextInt(pokers.size());
//兩張牌交換位置
Poker p1=(Poker) pokers.get(index1);
Poker p2=(Poker) pokers.get(index2);
pokers.set(index1,p2);
pokers.set(index2,p1);
}
}
}
(二)String類一個知識點
String類已經對Object的hashCode方法進行了重寫。
String類重寫的hashCode方法得到的數字是根據字符串的內容(字符)計算出來的。
且String類實現了一個Comparable接口,字符串具有可比較性。
public class register_test {
public static void main(String[] args) {
String str1="hello";
String str2=new String("hello");
System.out.println("內容一樣麼?"+str1.equals(str2));//true
System.out.println("是同一個對象麼?"+str1==str2);//false
System.out.println("str1哈希碼值:"+str1.hashCode());//99162322
System.out.println("str2哈希碼值:"+str2.hashCode());//99162322
}
}
(三)TreeSet類
集合體系:
Collection(單列集合的根接口,包含兩個子接口List Set)
List 如果是實現了List接口的集合類具備的特點是:有序、可重複
List接口的實現類:
ArrayList:(實現原理):ArrayList的底層維護了一個Object數組,
(特點):查詢速度快(數組元素間地址連續),增刪慢(增:若容量不夠,則會開闢新的數組,並把舊數組內容複製到新數組中;刪:刪除元素之後,其後的元素都要移動。)。
(應用場景):操作的數據查詢較多,增刪較少。比如:圖書館。
LinkedList:(實現原理):底層使用鏈表數據結構實現。
(特點):查詢速度慢(鏈表元素間地址不連續),增刪快(更改指針指向即可。不涉及到拷貝和檢查長度)
Vector(瞭解):(實現原理):底層也維護了一個Object數組,但是Vector是線程安全的,操作效率低。
Set 如果是實現了Set接口的集合類具備的特點是:無序、不可重複
Set接口的實現類:(Set實現類都不含重複元素,但是每個實現類判斷重複元素的標準不同。 )
HashSet:(實現原理):底層使用哈希表支持。
(特點):存取的速度快。元素值根據hashCode即可算出即存儲位置。
TreeSet:(實現原理):底層使用紅黑樹(二叉樹)實現。
(特點):可以對元素存儲排序。
TreeSet要注意的事項:
1.往TreeSet添加元素的時候,如果元素本身具備自然順序的特性,那麼TreeSet就會按照元素自然順序排序。
2.往TreeSet添加元素的時候,如果元素本身不具備自然順序的特性,那麼元素所屬的類就必須要實現Comparable接口,把元素的比較規則定義在CompareTo()方法上。
3.往TreeSet添加元素的時候,如果元素本身不具備自然順序的特性,而且元素所屬的類沒有實現Comparable接口,那麼在創建TreeSet對象的時候就必須要傳入一個比較器對象。
4.在TreeSet中如果CompareTo返回的是0,說明兩個元素是同一個元素,後者不予添加。
5.如果元素已經實現了Comparable接口,但是創建TreeSet對象時又傳入了比較器對象,那麼比較規則優先使用比較器的。
推薦使用:比較器的優先級高,複用性更高,可定義多個比較器,需要哪個調用哪個。
比較器的創建格式:
class 類名 implements Comparator{}//一個比較器類
比較規則:紅黑樹(左小右大),添加的第一個節點爲根節點,其餘點依次與根節點及路徑上的點進行比較,構成紅黑樹,並自動調整節點位置,儘量減少比較次數,保持平衡。
例如:
/*
class Employee implements Comparable{//實現接口,元素才具備可比性
String name;
int age;
int salary;
public Employee(String name, int age, int salary) {
super();
this.name = name;
this.age = age;
this.salary = salary;
}
@Override
public String toString() {
return "姓名:"+this.name+" 年齡:"+this.age+" 薪水:"+this.salary+"}";
}
/*
元素與元素之間的比較規則定義在compareTo方法上。
返回值:負整數、零或正整數,根據此對象是小於、等於還是大於指定對象。
//若返回0,則視爲同一個元素
*/
/*
public int compareTo(Object obj) {
Employee emp=(Employee)obj;
System.out.println(this.name+"compareTo"+emp.name);//看哪兩者比較過
return this.salary-emp.salary;//從小到大
//return emp.salary-this.salary;//從大到小
}
}
*/
class Employee{//實現接口,元素才具備可比性
String name;
int age;
int salary;
public Employee(String name, int age, int salary) {
super();
this.name = name;
this.age = age;
this.salary = salary;
}
@Override
public String toString() {
return "{姓名:"+this.name+" 年齡:"+this.age+" 薪水:"+this.salary+"}";
}
}
//比較器
class AgeComparator implements Comparator{
public int compare(Object obj1,Object obj2) {
Employee e1=(Employee)obj1;
Employee e2=(Employee)obj2;
return e1.age-e2.age;//按照年齡從小到大
}
}
public class treeset_demo1 {
public static void main(String[] args) {
//創建一個比較器對象
AgeComparator agecomparator=new AgeComparator();
TreeSet tree=new TreeSet(agecomparator);
tree.add(new Employee("小米", 22 ,6666));
tree.add(new Employee("大米", 25, 8888));
tree.add(new Employee("黑米", 26, 1888));
tree.add(new Employee("紅米", 28, 7777));
tree.add(new Employee("黃豆", 88, 7777));
System.out.println(tree);
}
}
(四)泛型
泛型:是jdk1.5出現的新特性。
泛型的好處:
1.可以把運行時出現的問題提前至編譯時。
2.避免了無謂的強制類型轉換。
使用泛型要注意的事項:
1.泛型中沒有多態的概念,左右兩邊的數據類型必須一致,或者只寫一邊的泛型。
推薦:兩邊都寫同樣數據類型的泛型。只寫一邊是爲了新老系統的兼容性。
public class genericity_demo1 {
public static void main(String[] args) {
//容器中只能存儲String類型的數據。
ArrayList<String> list=new ArrayList<String>();//泛型
list.add("aa");
list.add("mm");
list.add("gg");
for(int i=0;i<list.size();i++) {
String str=list.get(i);
System.out.println(str.toUpperCase());
}
}
自定義泛型:自定義泛型可以理解爲是一個數據類型的變量或是一個數據的佔位符。
函數自定義泛型的格式:
修飾符<聲明自定義格式> 返回值類型 函數名(形參列表...){
}
函數自定義泛型要注意的細節:
1.函數上自定義泛型的具體數據類型是在調用該函數的時候,傳遞實參數據的時確定具體數據類型的。
2.自定義泛型使用的標識符可以是自定義的,只要符合標識符的命名規則即可。但是一般自定義泛型使用的標識符都是單個字母。
3.泛型中是不能使用基本數據類型數據的,如果需要使用基本數據類型數據,那麼就要使用基本數據類型對應的包類型。
int------->Integer
float----->Float
double---->Double
char------>Character
boolean--->Boolean
byte------>Byte
short----->Short
long------>Long
public class genericity_demo2 {
public static void main(String[] args) {
String str=print("abc");
Integer num=print(123);
}
public static <T> T print(T o) {//T type E element
return o;
}
}
自定義泛型類的格式:
class 類名 <自定義的泛型>{}
泛型類要注意的事項:
1.類上聲明的自定義泛型的自定義數據類型是在使用該類創建對象時確定的。
2.如果一個類已經聲明瞭自定義泛型,該類創建對象的時候,若不指定自定義泛型的具體數據類型,那麼默認爲Object類型。
3.靜態的方法不能使用類上聲明的自定義泛型,若需要使用,在方法上聲明。(因爲自定義類的數據類型是在創建對象時確定,但靜態方法不需要創建對象)。
class MyArrays<T>{//數組工具類兩個方法
//反轉
public void reverse(T[] arr) {
for(int start=0,end=arr.length-1;start<end;start++,end--) {
T temp=arr[start];
arr[start]=arr[end];
arr[end]=temp;
}
}
public String toString(T[] 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();//返回類型String
}
public static <T> void test(T[] arr) {//與類上的T無關
}
}
public class genericity_demo3 {
public static void main(String[] args) {
Integer[] arr= {1,2,3,4,5};//泛型不能使用基本數據類型數據
//MyArrays<Integer> myarrays=new MyArrays();//這樣將所有的T都換成Integer,只能操作整型
MyArrays myarrays=new MyArrays();//這樣可以操作所有的數據類型
myarrays.reverse(arr);
System.out.println(myarrays.toString(arr));
}
}
泛型接口要注意的細節:
1.接口上自定義泛型的具體數據類型是在實現該接口的時候確定的。
2.如果一個接口已經自定義了泛型,在實現該接口的時候沒有指定自定義泛型的數據類型,那麼默認爲Object類型。
3.如果想在創建接口實現類對象的時候再指定接口的自定義泛型的具體數據類型。需要在實現類定義的時候聲明自定義泛型。
interface Dao<T>{
public void add(T t);
}
class UserDao<T> implements Dao<T>{
@Override
public void add(T t) {}
}
public class genericity_demo4 {
UserDao<String> user=new UserDao<String>();
user.add("123");
}
泛型的上下限:
泛型的通配符:?
? super Integer 泛型的下限:表示只能用於Integer或是Integer的父類類型數據。
? extends Number 泛型的上限:表示只能用於Number或是Number的子類類型數據。
public class genericity_demo5 {
public static void main(String[] args) {
ArrayList<Integer> list=new ArrayList<Integer>();
ArrayList<Number> list2=new ArrayList<Number>();
ArrayList<Double> list3=new ArrayList<Double>();
show(list3);
}
//定義一個方法可以接受任意類型的集合對象,接受的集合對象只能存儲Integer以及Integer父類類型的數據。
public static void print(Collection<? super Integer> c) {//Collection是集合的根接口,只能傳過來該接口的實現類集合對象
}
//定義一個方法可以接受任意類型的集合對象,接受的集合對象只能存儲Number以及Number子類類型的數據。
public static void show(Collection<? extends Number> c) {
}
}
(五)map接口
存儲成對的數據用到雙列集合。
雙列集合體系:
Map: 實現了Map接口的集合類具備的特點:存儲的數據都是以鍵值對的形式存在的,鍵(key)不能重複,值(value)可以重複。
HashMap
TreeMap
Hashtable(瞭解)
map接口的實現類:
HashMap
Map接口的方法:
增
put() 返回以前與key相關的value值,如果沒有針對key的映射關係,則返回null.
putAll(<>)
刪
clear()
remove() 根據鍵刪除一個元素,返回的是鍵對應的值
判斷
containsKey() 是否存在指定的鍵
containsValue 是否存在指定的鍵
isEmpty()
獲取
get()
size()
迭代
keySet()
values()
entrySet()
public class genericity_demo6 {
public static void main(String[] args) {
Map<String,String> map=new HashMap<String,String>();
map.put("汪峯","章子怡");
map.put("張傑","謝娜");
map.put("張若昀","唐藝昕");
map.put("鄧超","孫儷");
/*
Map<String,String> map2=new HashMap<String,String>();
map2.put("小米","黃豆");
map2.put("大米","黑豆");
map.putAll(map2);
刪除
map.clear();
*/
//System.out.println(map.remove("鄧超"));
/*
System.out.println("是否存在指定的鍵:"+map.containsKey("鄧超"));
System.out.println("是否存在指定的值:"+map.containsValue("謝娜"));
//map.clear();
//map=null;//報錯,空指針異常
System.out.println("根據鍵獲取對應的值:"+map.get("張傑"));
System.out.println("是否爲空:"+map.isEmpty());
*/
/*
//遍歷方式一:可以用KeySet方法遍歷,KeySet方法返回的集合只是包含了所有的鍵,沒有包含值。
Set set=map.keySet();//把map集合中所有Key的數據存儲到Set集合中返回。
Iterator<String> it=set.iterator();
while(it.hasNext()) {
String key=it.next();
System.out.println("鍵:"+key+" 值:"+map.get(key));
}*/
//遍歷方式二:values方法,返回的只是map集合中的所有值,沒有鍵。
/*Collection<String> col=map.values();//把map集合所有值存儲到集合中返回
Iterator<String> it=col.iterator();//表示抓取的數據類型只能是String
while(it.hasNext()) {
String value=it.next();
System.out.println("值:"+value);S
}*/
Set<Entry<String,String>> entrys=map.entrySet();
Iterator<Entry<String,String>> it=entrys.iterator();
while(it.hasNext()) {
Entry<String,String> entry=it.next();
System.out.println("鍵:"+entry.getKey()+" 值:"+entry.getValue());
}
System.out.println("集合的元素:"+map);
}
}