1. 程式人生 > 實用技巧 >java資料結構(list、map、set實現)

java資料結構(list、map、set實現)

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==null
){ 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; } }
View Code

遍歷陣列改進版,折中查詢,這樣效率高。注意左移相當於乘以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泛型與陣列

這樣就是錯的,宣告時沒有問題,但使用時出錯,都不知道是什麼型別的陣列怎麼開闢空間呢

// 獲取陣列中所有的值和獲取某個索引處的值