递归泛型二叉树、List、Set、Map、队列Queue

一。 二叉树递归泛型版
泛型比较大小转成Comparable调用compareTo

将泛型值t强转Comparabl,调用compareTo用来比较
         public class Treetwo2<T> {
    public class Node<T> {
        private T date;
        private Node<T> lift;
        private Node<T> right;

        private Node(T date) {
            this.date = date;
        }
    }
    private Node root;
    private  void addToNode(Node node,T t){
        if(((Comparable)t).compareTo(node.date)<0){//将泛型值t强转Comparabl,调用compareTo用来比较
            //date加到左边
            if(node.lift==null){//节点左边如果为空把t给左边并return退出
                node.lift=new Node<T>(t);
                return;
            }
            addToNode(node.lift,t);//如果节点左边不空,继续调用本身访问左边下个节点
        }
        else if (((Comparable)t).compareTo(node.date)>0){
            //date右移动
            if(node.right==null){
                node.right=new Node<T>(t);
                return;
            }
            addToNode(node.right,t);
        }
    }
    public void add(T t){
        if(root==null){
            root=new Node(t);
            return;
        }else{
            addToNode(root,t);
        }
    }

    public void trivelNode(Node<T> node){
        if(node.lift!=null){
            trivelNode(node.lift);
        }
        System.out.println(node.date);
        if(node.right!=null){
            trivelNode(node.right);
        }
    }
    public void trivel(){
        trivelNode(root);
    }
}

二。 List
List(I): ArrayList:数组 LinkedList:双向链表 Vector
可使用下标
add(index, E e), remove(index)
get(index), set(index, E e)

1.ArrayList和LinkedList效率比较

public class ArryAndLinked {
    public static void main(String[] args) {
        ArrayList<String> arrayList=new ArrayList<>();
        LinkedList<String> linkedList=new LinkedList<>();
        for(int i=0;i<1000000;i++){
            arrayList.add("1");
            linkedList.add("1");
        }
        //比较从头部访问的速度
        long time1=System.currentTimeMillis();
        arrayList.get(10);
        long time2=System.currentTimeMillis();
        System.out.println("头部访问速度"+(time2-time1));
        long time3=System.currentTimeMillis();
        linkedList.get(10);
        long time4=System.currentTimeMillis();
        System.out.println("头部访问速度"+(time4-time3));
        //比较从中间访问的速度
        long time5=System.currentTimeMillis();
        arrayList.get(500000);
        long time6=System.currentTimeMillis();
        System.out.println("中部访问速度"+(time6-time5));
        long time7=System.currentTimeMillis();
        linkedList.get(500000);
        long time8=System.currentTimeMillis();
        System.out.println("中部访问速度"+(time8-time7));
        //比较从尾部访问的速度
        long time9=System.currentTimeMillis();
        arrayList.get(980000);
        long time10=System.currentTimeMillis();
        System.out.println("尾部访问速度"+(time10-time9));
        long time11=System.currentTimeMillis();
        linkedList.get(980000);//linkedList是双向链表
        long time12=System.currentTimeMillis();
        System.out.println("尾部访问速度"+(time12-time11));
        System.out.println("----------------------");
        //比较插入速度
        //头部插入速度
        long time01=System.currentTimeMillis();
        arrayList.add(10,"2");//ArryList每插入一个,后面所有都要向后面移
        long time02=System.currentTimeMillis();
        System.out.println("头部访问速度"+(time02-time01));
        long time03=System.currentTimeMillis();
        linkedList.add(10,"2");//链表插入可以在这个位置直接插入,应为其空间位置不是连续的
        long time04=System.currentTimeMillis();
        System.out.println("头部访问速度"+(time04-time03));
        //中部插入
        long time05=System.currentTimeMillis();
        arrayList.add(500000,"2");//ArryList每插入一个,后面所有都要向后面移,所以插入位置越靠后越快
        long time06=System.currentTimeMillis();
        System.out.println("头部访问速度"+(time06-time05));
        long time07=System.currentTimeMillis();
        linkedList.add(500000,"2");
        long time08=System.currentTimeMillis();
        System.out.println("头部访问速度"+(time08-time07));
        //尾巴部插入
        long time09=System.currentTimeMillis();
        arrayList.add(980000,"2");
        long time010=System.currentTimeMillis();
        System.out.println("头部访问速度"+(time010-time09));
        long time011=System.currentTimeMillis();
        linkedList.add(980000,"2");
        long time012=System.currentTimeMillis();
        System.out.println("头部访问速度"+(time012-time011));
    }
}

2.LinkedList独有的方法 - 了解
linkList.addFirst("");
linkList.addLast("");
linkList.removeFirst();
linkList.removeLast();
linkList.getFirst();
linkList.getLast();

三。Set
1. 实现类 HashSet:
HashSet: 散列表/无序的, 不是随机!! 不允许重复元素
add原理: 详见图
remove原理
结论: hashCode和equals要一起重写
注意: equals方法判断相同的两个对象, hashCode方法结果一定要一致
equals判断不相同的两个对象, hashCode结果要尽量不一样

public class Studengt {
    private int age;
    private String name;
    public Studengt(int age,String name){
        this.age=age;
        this.name=name;
    }

    @Override
    public String toString() {
        return  age +
                ", "+name+'\n';
    }


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Studengt studengt = (Studengt) o;
        return age == studengt.age &&
                Objects.equals(name, studengt.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(age, name);
    }
    加上get/set代码

public class HashCode1 {
    public static void main(String[] args) {
        Set<Studengt>set=new HashSet<>();
        set.add(new Studengt(18,"张三"));
        set.add(new Studengt(18,"张三"));
        set.add(new Studengt(20,"王二"));
        set.add(new Studengt(20,"李久"));
        System.out.println(set);
        System.out.println("----------");
        Studengt s1=new Studengt(18,"张三");
        Studengt s2=new Studengt(30,"六六");
        Studengt s3=new Studengt(18,"离奇");
        Set<Studengt>set1=new HashSet<>();
        set1.add(s1);
        set1.add(s2);
        set1.add(s3);
        System.out.println(set1);
        s1.setAge(22);
        set1.remove(s1);//s1的属性改变之后其哈希码改变导致和之前哈希地址不同,无法找到删除s1
        System.out.println(set1);
    }
}

①判断元素是否相同,是否要add进去:
Student没有重写equals和hashCode, 全部new出来的哈希码不同

重写了equals方法, 但是没有重写hashCode, 全部new出来的哈希码不同

重写了hashCode方法, 但是没有重写equals, new出的元素数组地址相同,但无法比较数组地址下的链表内容

重写了equals和hashCode方法, 能找到数组地址并比较数组地址下的链表内容,相同的就不添加
② 元素属性值发生了改变,用remove移除,移除的时候,重新计算位置,发现位置上找不到s1对象,不会移除。
③ Object中 hashCode() 方法默认得到的是 对象的物理地址
hashCode没有重写, 所有对象的哈希值都不一样
但哈希值不一样, 定位到的set中的位置, 可能相同

2 . SortedSet(I)接口
|- 实现类TreeSet: Comparable Comparator
特点: 不允许重复, 和equals方法无关
取决于 compare 或者 compareTo 方法

public class TreeSet1 {
    public static void main(String[] args) {
    // 可以通过构造方法, 传入比较器
        Set<String>set=new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {//相同就不会输出
                return o1.length()-o2.length();
            }
        });
        set.add("aaa");
        set.add("bbbb");
        set.add("gg");
        set.add("oooop");
        System.out.println(set);
        System.out.println("_____________");
        Set<Studengt>set1=new TreeSet<>(new Comparator<Studengt>() {
            @Override
            public int compare(Studengt o1, Studengt o2) {
                return o1.getAge()-o2.getAge();
            }
        });
        set1.add(new Studengt(18,"李四"));
        set1.add(new Studengt(18,"王五"));
        set1.add(new Studengt(20,"李四"));
        System.out.println(set1);
        System.out.println("______________");
        Set<Integer>set2=new TreeSet<>();//没重写Compalable也会用默认方法排序
        set2.add(1);
        set2.add(2);
        set2.add(3);
        set2.add(3);
        set2.add(7);
        set2.add(5);
        System.out.println(set2);
    }
}

四。Map
Map(I): 映射表 key->value, 通过key 获得value
Map中的key, 单独的一部分, 就是Set
|- HashMap
|- TreeMap
1.HashMap
常用API:
V put(key, value)
V remove(key)
V get(key)
containsKey containsValue isEmpty size…
putAll

public class Map1 {
    public static void main(String[] args) {
        Map<Integer,String>map=new HashMap<>();
        //1添加.put的返回值:对应key之前的value内容
        map.put(1,"黑土");
        map.put(4,"黑龙江");
        map.put(3,"铁岭");
        map.put(2,"白云");
        //会自动用默认的hashcode排序
        System.out.println(map);
        //2移除。remove返回值:被移除前的value 
        map.remove(1);
        String m=map.remove(3);
        System.out.println("remove返回值"+m);
        System.out.println(map);
        //3修改集合中的元素
        String s=map.put(2,"乌云");
        map.put(5,"老树");
        System.out.println("put返回值"+s);//put的返回值:对应key之前的value内容
        System.out.println(map);
        //4获得get  返回值value
        System.out.println(map.get(2));
    }
}

2.迭代Map对应的三个方法
entrySet()
keySet()
values()

public class MapTrivel {
    public static void main(String[] args) {
        Map<String,String>map=new HashMap<>();
        map.put("黑土","11236");
        map.put("白云","7764");
        map.put("简自豪","7764");
        map.put("郭德纲","7764");
        //①获取所有的键,成键集
        Set<String>keys=map.keySet();
        //遍历键集
        for(String ke:keys){
            //ke为键。然后获取对应value
            String value=map.get(ke);
            System.out.println(ke+"="+value);
        }
        System.out.println("------------");

        //②获取所有entry对象。键值对
        Set<Entry<String,String>> entrySet=map.entrySet();//如果没导包Entry写成Map.Entry
        //遍历得到的每一个entry对象
        for(Entry<String,String>entry:entrySet){
            //将键值对分解
            String key=entry.getKey();//获取key
            String value=entry.getValue();//获取value
            System.out.println(key+"="+value);
        }
        System.out.println("-------------");

        //③只能遍历value
        Collection<String>value=map.values();
        for(String va:value){
            System.out.println(va);
        }
    }
}

3.判断字符串中各字符出现的个数

public class Exice {//判断字符出现的次数
    public static void main(String[] args) {
        Scanner consol=new Scanner(System.in);
        String str=consol.next();
        //将字符转为字符数组
        char[] arr=str.toCharArray();

        Map<Character,Integer>map=new HashMap<>();
        //遍历数组进行统计
        for(Character c:arr){
            //判断是否首次出现
            Integer ori=map.get(c);
            if(ori==null){
                ori=0;
            }
          map.put(c,ori+1);
        }
        System.out.println(map);
    }

五。队列Queue
Queue(I): - 队列(offer/poll/peek)
|- Deque(I) - 双端队列(offerFirst/offerLast…)
- 栈(push/pop)
|- LinkedList
1。单向队列Queue

public class Demo01Queue {
    public static void main(String[] args) {
        // 1.创建队列 - 先进先出
        Queue<String> qu = new LinkedList<>();
        // 2.进队列的方法
        qu.offer("哈哈哈");
        qu.offer("嘻嘻嘻");
        System.out.println(qu);
        // 3.获取队列头元素的方法
        String s1 = qu.peek(); // -- 只是查看访问
        System.out.println("队列头: " + s1);
        System.out.println("队列: " + qu);
        s1 = qu.poll(); // -- 获取队列头元素,并将元素从队列中移除
        System.out.println("队列头2: " + s1);
        System.out.println("队列2: " + qu);
    }
}

2.双向队列Deque

public class Demo02Deque {
    public static void main(String[] args) {
        // 1.创建一个双端队列的方法
        Deque<String> dq = new LinkedList<>();
        // 2.拥有队列相关的所有方法 offer peek poll
        dq.offer("哈哈哈");
        dq.offer("嘻嘻嘻");
        // 3.可以从队列头和尾加元素
        dq.offerFirst("hahaha");
        dq.offerLast("heihei"); // 等同于offer方法
        System.out.println(dq);
        // 4.可以从队列头和尾取元素
        String s1 = dq.pollFirst(); // 等同于poll
        System.out.println("队列头: " + s1);
        System.out.println("队列: " + dq);

        s1 = dq.pollLast();
        System.out.println("队列尾: " + s1);
        System.out.println("队列: " + dq);
    }
}
public class Demo03Stack {
    public static void main(String[] args) {
        // Deque当你使用它的 push 和 pop 方法时, 他就变成了栈
        // 链表栈
        Deque<String> stack = new LinkedList<>();
        stack.push("a");
        stack.push("b");
        stack.push("c");
        System.out.println(stack);
        String s = stack.pop();
        System.out.println("栈顶元素: " + s);
        System.out.println("栈: " + stack);

        // 栈: 数组栈
        Stack<String> stack2 = new Stack<>();
        stack2.push("h");
        stack2.push("i");
        System.out.println(stack2);

        String s2 = stack2.pop();
        System.out.println("stack2的栈顶: " + s2);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值