zoukankan      html  css  js  c++  java
  • java学习笔记(四)---泛型及集合框架

    1、泛型

     当做一些集合的统一操作的时候,需要保证集合的类型的统一性,此时需要泛型进行限制

       优点

          1、数据的安全

          2、获取数据的效率比较高

       给集合中的元素设置相同类型是泛型的基本需求

       使用:

          在定义对象的时候,通过<>中设置合理的类型来进行实现

    泛型的高阶运用

      1、泛型类

         在定义类的时候,在类名的后面添加<T,E,K,V>,起到占位的作用,类中的方法的返回类型和属性的类型都可以使用

    类的声明

    package com.yfbill.test;
    
    public class Bill<E>{   //这里的E是表示实例化的时候指定的泛型
        private String name;
        private E prop;     //这里的E是表示类名后的那个E类型
    
        public Bill(E prop, String name) {
            this.name = name;
            this.prop = prop;
        }
    
        public E getProp() {
            return this.prop;
        }
    }

    类的调用

    public class Test {
        public static void main(String[] args) {
            //可以是一个字符串
            Bill<String> b = new Bill<>("this is test", "bill");
            System.out.println(b.getProp());
            //也可以是一个对象
            Bill<Dog> d = new Bill<>(new Dog("aa",  2), "unKnown");
            System.out.println(d.getProp());
        }
    }

      2、泛型接口  

        在定义接口的时候,在接口的名称后面添加<T,E,K,V>

    public interface ICheck<E> {  //这里的E相当需要继承的时候指定
        public E getProp();
    
        public void showProp(E obj);
    }

          1、子类在实现接口的时候,可以不填写泛型类型,只填写占位符,此时在创建具体子类对象的时候才决定使用什么类型

    类的声明

    public class Bill<E> implements ICheck<E>{  //需要在调用的时候外部指定
    
        private E prop;
    
        public Bill (E prop) {
            this.prop = prop;
        }
    
        @Override
        public E getProp() {
            return this.prop;
        }
    
        @Override
        public void showProp(E obj) {
            System.out.println(obj);
        }
    }

    类的调用

    public class Test {
        public static void main(String[] args) {
            //可以是一个字符串
            Bill<String> b = new Bill<>("this is test");
            System.out.println(b.getProp());
            //也可以是一个对象
            Bill<Dog> d = new Bill<>(new Dog("aa",  2));
            d.showProp(new Dog("bbb", 1));
        }
    }

        2、子类在实现泛型接口的时候,只在实现父类的接口的时候指定父类的泛型类即可,此时,测试方法中的泛型类型必须要跟子类保持一致

    类的声明

    public class Bill implements ICheck<String>{  //这里的String表示具体的类型的,而不是占位符,那么默认外部调用就全部是String类型了
    
        @Override
        public String getProp() {
            return "are you ok???";
        }
    
        @Override
        public void showProp(String str) {
            System.out.println(str);
        }
    }

    类的调用

    public class Test {
        public static void main(String[] args) {
            //这里默认是字符串了
            Bill b = new Bill();
            System.out.println(b.getProp());
        }
    }

      3、泛型方法  

         在定义方法的时候,指定方法的返回值或参数是自定义的占位符,可以是父类类名中的E也可以是自定义的Q,只不过在使用Q的时候,需要使用<Q>定义在返回值的前面。(这里的Q可以用其他字母替代)

    类的声明

    public class Bill<E>{
        public E prop;
        public Bill (E prop) {
            this.prop = prop;
        }
        /**
         * 调用的是类上声明的泛型类型
         * @return
         */
        public E take() {
            return this.prop;
        }
    
        /**
         * 传入一个与类上的声明不一样的泛型类型
         * @param other
         * @param <T>
         */
        public <T> void show (T other) {
            System.out.println(other);
        }
    }

    类的调用

    public class Test {
        public static void main(String[] args) {
            //这里默认是字符串了
            Bill<String> b = new Bill<>("this is test");
            System.out.println(b.take());
            b.show(new Dog("aa", 12));
        }
    }

      4、泛型的上限(工作中用的不多,但是查询API的时候会经常用到)

         如果父类确定了,所有的子类都可以直接使用

      5、泛型的下限

         如果父类确定了,子类的所有父类都可以直接传传递使用

     2、Map类型

     特点:key-value映射

      1、HashMap

         key 无序,唯一

         value 无序,不唯一

      2、LinkedHashMap

           有序的HashMap,速度快

      3、TreeMap

         有序,速度没有hash快

      

      HashMap与Hashtable的区别

         1、HashMap线程不安全,效率比较高,hashtable线程安全,效率低

            2、HashMap中key和value都可以为空,hashtable不允许为空

      HashMap相关的api

    public class Test {
        public static void main(String[] args) {
            HashMap<Integer, String> map = new HashMap<>();
            HashMap<Integer, String> list = new HashMap<>(Map.of(10, "first", 11, "second", 12, "third"));
            //添加数据
            map.put(1, "this is first");
            map.put(2, "this is second");
            map.putIfAbsent(3, "what are you doing");//如果已有数据,那么返回对应键值的值,否则添加对应的关联,并且返回null
            map.putAll(list);
    
            //查询数据
            System.out.println(map.size());
            System.out.println(map.isEmpty());
            System.out.println(map.keySet());
            System.out.println(map.values());
            System.out.println(map.containsKey(3));
            System.out.println(map.containsValue("third"));
            System.out.println(map.get(2));
            System.out.println(map.getOrDefault(5, "undefined"));
    
            //遍历操作
            System.out.println("-------------------------------------");
            for(Integer item: map.keySet()) {
                System.out.println("key的值:" + item + ", value的值是:" + map.get(item));
            }
    
            for(String item: map.values()) {
                System.out.println(item);
            }
    
            Set<Map.Entry<Integer, String>> entries = map.entrySet();
            for(Map.Entry<Integer, String> iter: entries) {
                System.out.println("key的值:" + iter.getKey() + ", value的值:" + iter.getValue());
            }
    
            map.forEach((Integer key, String val) -> System.out.println("key:" + key + ", val:" + val));
    
            System.out.println("===============================");
    
            //修改数据
            HashMap<Integer, String> arr = new HashMap<>(){{ this.put(1, "aaaa"); this.put(2, "bbbb"); }};
    //        ArrayList<Integer> abc = new ArrayList<>(){{  this.add(1); this.add(2); this.add(12); }};
            System.out.println(arr.merge(12,"ok", (String a, String b) -> a + b));  //如果有值则进行替换,否则为新增
            arr.compute(2, (Integer k, String v) -> v + "yes"); //根据已知的 k v 算出新的v并put。返回值为新值, 如果无此key,那么oldVal为null,lambda中涉及到oldVal的计算会报空指针
            arr.computeIfAbsent(100, (Integer k) -> k + "haha"); //当key不存在的时候才执行表达式, 如果存在,那么不执行put,返回现有的值
            arr.computeIfPresent(1000, (Integer k, String v) -> "this is test, ok????"); //当key值存在才执行,如果不存在则返回null
            map.replace(1, "my name is good");
            map.replace(2, "this is second", "haha"); //只有值匹配正确才能进行替换
            map.replaceAll((Integer key, String val) -> {
                if(key <= 3) {
                    return "this is test";
                }
                return val;
            });
    
            //删除数据
            map.remove(1);
            map.remove(2, "this is test");
            map.clear();
        }
    }

       TreeMap独有的一些api

    public class Test {
        public static void main(String[] args) {
            TreeMap<Integer, String> map = new TreeMap<>(Map.of(1, "first", 2, "second", 3, "third", 4, "four"));
    
            System.out.println(map.ceilingEntry(2));//比指定大的最小值  含本身
            System.out.println(map.floorEntry(2));  //比指定小的最大值  含本身
            System.out.println(map.higherEntry(2)); //比指定大的最小值  不含本身
            System.out.println(map.lowerEntry(2));  //比指定小的最大值  不含本身
            System.out.println(map.higherKey(2));
            System.out.println(map.lowerKey(2));
            System.out.println(map.headMap(3));
            System.out.println(map.headMap(3, true));  //如为true表示包含本身
            System.out.println(map.descendingKeySet()); //提取key然后再进行倒序排列
            System.out.println(map.descendingMap()); //进行倒序排列
            System.out.println(map.subMap(2, true, 4, true)); //对map进行截取,如果为true则包含本身
            System.out.println(map.tailMap(2, true));
        }
    }

    集合总结

    名称 存储结构 顺序 唯一性 查询效率 添加/删除效率
    ArrayList 顺序表 有序(添加) 不唯一 索引查询效率高
    LinkedList 链表 有序(添加) 不唯一  低  最高
    HashSet 哈希表 无序 唯一 最高 最高
    HashMap 哈希表 key无序 key唯一 最高 最高
    LinkedHashSet 哈 + 链 有序(添加) 唯一 最高 最高
    LinkedHashMap 哈 + 链 key有序(添加) key唯一 最高 最高
    TreeSet 二叉树(红黑树) 有序(升序) 唯一 中等 中等
    TreeMap 二叉树(红黑树) 有序(升序) key唯一 中等 中等

     

     

     

     

     

     

     

     

     

    3、collections工具类的使用

    public class Test {
        public static void main(String[] args) {
            ArrayList<Integer> list = new ArrayList<>();
            ArrayList<Integer> arr = new ArrayList<>(Arrays.asList(100, 200, 300));
            //对集合进行批量添加
            Collections.addAll(list, 7, 8, 0, 1, 3, 5, 2, 4, 6);
            //对list进行反向排序
            Collections.reverse(list);
            //对集合进行排序
            Collections.sort(list);
            Collections.sort(list, (Integer a, Integer b) -> b - a);
            //把arr的项复制到list中,前提是arr的长度必需要小于等于list的长度
            Collections.copy(list, arr);
            //把指定的List对象以某值进行填充
            Collections.fill(list, 1000);
            //统计指定的元素出现的次数
            int count = Collections.frequency(list, 1000);
            //查询最大值
            System.out.println(Collections.max(arr));
            //查询最小值
            System.out.println(Collections.min(arr));
            //对集合进行随机排序
    //        Collections.shuffle(arr);
            //判断两个集合没有交集
            System.out.println(Collections.disjoint(arr, list));
            //把两个元素的位置进行调换
            Collections.swap(arr, 2, 1);
    
            //binarySearch  表示进行二分查找,前提是要先排好序
        }
    }

     Arrays的常用方法

    public class Test {
        public static void main(String[] args) {
            ArrayList<Integer> arr = new ArrayList<>();
            Collections.addAll(arr, 1, 2, 3, 4, 5, 6, 7);
            //把指定的转成list类型
            List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
            //把list类型转成数组
            Object[] array = list.toArray();
        }
    }
  • 相关阅读:
    网络七层协议
    Sizeof与Strlen的区别与联系
    Java面试宝典(说说&和&&的区别)
    Java se基础(类的属性及关键字)
    了解java中垃圾回收机制
    MYSQL常用函数(系统信息函数)
    MYSQL常用函数(类型转化函数)
    MYSQL常用函数(格式化函数)
    MYSQL常用函数(控制流函数)
    【CF-1362】B. Johnny and His Hobbies
  • 原文地址:https://www.cnblogs.com/rickyctbu/p/13379169.html
Copyright © 2011-2022 走看看