java資料結構(list、map、set實現)
阿新 • • 發佈:2020-09-01
1.設定斷點,debug,看varibables,run-->stepover,右上角點java退出debug
package one.eight; public class ImplementLinkedList { private Node first; private Node last; private int size; //往連結串列末尾插新的節點 public void add(Object obj){ Node n = new Node(); if(first==nullView Code){ n.setPrevious(null); n.setObj(obj); n.setNext(null); first = n; last = n; }else{ //直接往last節點後增加新的節點 n.setPrevious(last); n.setObj(obj); n.setNext(null); last.setNext(n); last= n; } size++; } public int size(){ return size; } private void rangeCheck(int index){ if(index<0||index>=size){ try { throw new Exception(); } catch (Exception e) { e.printStackTrace(); } } }public Object get(int index){ //2 陣列直接就可以找到index,但連結串列不行 rangeCheck(index); //index越界處理,index<0或者index>=size就丟擲一個異常 /* // 0 1 2 3 4 Node temp = node(index); if(temp!=null){ return temp.obj; } return null; */ Node temp = null; if(first!=null){ temp = first; for(int i=0;i<index;i++){ temp = temp.next; } } return temp.obj; } //遍歷節點 public Node node(int index){ Node temp = null; if(first!=null){ if (index < (size >> 1)) { temp = first; for(int i=0;i<index;i++){ temp = temp.next; } }else{ temp = last; for (int i = size - 1; i > index; i--){ temp = temp.previous; } } } // LinkedList l; return temp; } public void remove(int index){ Node temp = node(index); if(temp!=null){ Node up = temp.previous; Node down = temp.next; up.next = down; down.previous = up; size--; } } //往連結串列哦任意處插入節點 public void add(int index,Object obj){ Node temp = node(index); Node newNode = new Node(); newNode.obj = obj; if(temp!=null){ Node up = temp.previous; up.next = newNode; newNode.previous = up; newNode.next = temp; temp.previous = newNode; size++; } } public static void main(String[] args) { ImplementLinkedList list = new ImplementLinkedList(); list.add("aaa"); list.add("bbb"); // list.add(1,"BBBB"); list.add("ccc"); list.add("ddd"); list.add("eee"); // list.remove(1); System.out.println(list.get(3)); } } //用來表示一個節點 class Node { Node previous; //上一個節點,不加private訪問修飾符,預設的default在同一個包下的其他類都可以訪問 Object obj; Node next; //下一個節點 public Node() { } public Node(Node previous, Object obj, Node next) { super(); this.previous = previous; this.obj = obj; this.next = next; } public Node getPrevious() { return previous; } public void setPrevious(Node previous) { this.previous = previous; } public Object getObj() { return obj; } public void setObj(Object obj) { this.obj = obj; } public Node getNext() { return next; } public void setNext(Node next) { this.next = next; } }
遍歷陣列改進版,折中查詢,這樣效率高。注意左移相當於乘以2,右移相當於除以2(a>>1)
2.
package one.eight; /** *自定義實現Map的功能! *暫不完美! 每次查東西都要遍歷一次,效率低 *Map:存放鍵值對,根據鍵物件找對應的值物件.鍵不能重複! * */ public class ImplementMap { SxtEntry[] arr = new SxtEntry[990]; //SxtEntry型別的陣列,長度990 int size; public void put(Object key,Object value){ SxtEntry e = new SxtEntry(key,value); //arr[size++] = e; //解決鍵值重複的處理 for(int i=0;i<size;i++){ if(arr[i].key.equals(key)){ arr[i].value=value; return ; } } arr[size++] = e; } public Object get(Object key){ for(int i=0;i<size;i++){ if(arr[i].key.equals(key)){ return arr[i].value; } } return null; } public boolean containsKey(Object key){ for(int i=0;i<size;i++){ //遍歷陣列 if(arr[i].key.equals(key)){ return true; } } return false; } public boolean containsValue(Object value){ for(int i=0;i<size;i++){ if(arr[i].value.equals(value)){ return true; } } return false; } public static void main(String[] args) { ImplementMap m = new ImplementMap(); m.put("高琪", new Wife("楊冪")); m.put("高琪", new Wife("李四")); Wife w = (Wife) m.get("高琪"); System.out.println(w.name); } } class SxtEntry { Object key; Object value; public SxtEntry(Object key, Object value) { //右鍵source中Generate Constructor using field自動生成的帶參構造 super(); this.key = key; this.value = value; } }View Code
package one.eight; import java.util.LinkedList; /** * 自定義Map的升級版: * 1. 提高查詢的效率 * * */ public class ImplementMapPlus { LinkedList[] arr = new LinkedList[9]; //Map的底層結構就是:陣列+連結串列! int size; public void put(Object key,Object value){ SxtEntry e = new SxtEntry(key,value); //生成一個鍵值對物件,把它新增到容器裡,key和value都是物件,如key="張三",value="new wife("李四")" int hash = key.hashCode();//根據物件地址生成的一個數,想辦法把hashcode轉成0~9的數,把它放在陣列對應的index,這樣就不用每次遍歷了 //hash = hash<0?-hash:hash; int a = hash%arr.length; //這裡arr.length=9 if(arr[a]==null){ //如果陣列位置a處沒有指向任何東西 LinkedList list = new LinkedList(); //新建一個連結串列物件,讓陣列位置a處指向這個連結串列 arr[a] = list; list.add(e); //新建的連結串列物件是空的,此時把鍵值對SxtEntry物件新增到連結串列物件list中 }else{ //陣列a處已經指向了連結串列 LinkedList list = arr[a]; //取出陣列a處存放的連結串列(實際上是引用) for(int i=0;i<list.size();i++){ //遍歷這個陣列a處指向的連結串列 SxtEntry e2 = (SxtEntry) list.get(i); //取出遍歷到的鍵值對 if(e2.key.equals(key)){ e2.value = value; //鍵值重複直接覆蓋! return; } } arr[a].add(e); //arr[a]就指向那個連結串列物件 } //hashcode%999,a:1000-->1 b:10000-->13,但取的這個餘數有可能會重複 //int a = key.hashCode()%999; //arr[a] = e; } public Object get(Object key){ int a = key.hashCode()%arr.length; if(arr[a]!=null){ LinkedList list = arr[a]; //取出數組裡存放的連結串列 for(int i=0;i<list.size();i++){ SxtEntry e = (SxtEntry) list.get(i); //取出鍵值對 if(e.key.equals(key)){ return e.value; } } } //return arr[key.hashCode()%999]; return null; } public static void main(String[] args) { ImplementMapPlus m = new ImplementMapPlus(); m.put("高琪", new Wife("楊冪")); m.put("高琪", new Wife("李四")); Wife w = (Wife) m.get("高琪"); System.out.println(w.name); } }View Code
3.重寫hcode and equals方法可以藉助eclipse工具,右擊source----->generate hcode and equals 。Integer String Data等類都重寫了hashcode and equals方法
4.hashset實現
package one.eight; import java.util.HashMap; /** * 自定義自己的HashSet * @author Administrator * */ public class ImplementSet { HashMap map; private static final Object PRESENT = new Object(); //定義一個obj型別的常量,當做value值 public ImplementSet(){ map = new HashMap(); //無參構造 } public int size(){ return map.size(); } public void add(Object o){ map.put(o, PRESENT); //set的不可重複就是利用了map裡面鍵物件的不可重複! } public static void main(String[] args) { ImplementSet s = new ImplementSet(); s.add("aaa"); s.add(new String("aaa")); s.add("bbb"); s.add("bbb"); System.out.println(s.size()); } }View Code
5.這種通過索引遍歷方式只適合list,set沒有(因為set沒有順序)
set只能通過迭代器遍歷
java list中迭代器的實現
遊標
剛剛訪問的那個元素
只能刪剛剛遍歷到的物件,不能連續remove,因為remove會把lastret置為-1,再次呼叫remove時,程式碼剛開始lastret=-1丟擲異常
package cn.bjsxt.iterator; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; public class Test01 { public static void main(String[] args) { List list = new ArrayList(); list.add("aaa"); list.add("bbb"); list.add("ccc"); //通過索引遍歷List for(int i=0;i<list.size();i++){ System.out.println(list.get(i)); } //通過迭代器遍歷List for(Iterator iter2 = list.iterator();iter2.hasNext();){ String str = (String) iter2.next(); System.out.println(str); iter2.remove(); iter2.remove(); //這裡會丟擲異常 } System.out.println(list.size()+"******"); Set set = new HashSet(); set.add("高1"); set.add("高2"); set.add("高3"); //通過迭代器遍歷Set // Iterator iter = set.iterator(); // while(iter.hasNext()){ for(Iterator iter = set.iterator();iter.hasNext();){ String str = (String) iter.next(); System.out.println(str); } } }View Code
6.右擊一個工程
7.泛型
7.1
子類
重寫方法型別隨父類而定
7.2擦除
7.3型別萬用字元
編譯時看左邊,所以即使stu=new studentn<Fruit>,還是編譯錯誤,因為stu編譯時型別不確定
7.4 泛型巢狀
7.5泛型與陣列
這樣就是錯的,宣告時沒有問題,但使用時出錯,都不知道是什麼型別的陣列怎麼開闢空間呢
// 獲取陣列中所有的值和獲取某個索引處的值