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();
    }
}
原文地址:https://www.cnblogs.com/rickyctbu/p/13379169.html