zoukankan      html  css  js  c++  java
  • 泛型的定义以及set map接口

                          泛型(generic)

     泛型的概念

    泛型允许开发者在强类型程序设计语言(java)编写代码时定义一些可变部分,这些部分在使用前必须作出指明。

     泛型的擦除

    泛型在运行时已经被擦除了

     泛型应用

     泛型类

    一个类中属性的数据类型不确定时,具体是什么类型由使用来确定时,使用泛型。泛型类的形式

     泛型方法

    一个方法的参数类型不确定时,具体是什么类型由使用来确定可以考虑使用泛型方法。形式:

    public <T> void xxx(T a) {

    System.out.println(a);

    }

    泛型方法在调用时确定(指明)类型

    泛型方法在一定程度上优化了方法重载。

    多个同类型的泛型

    / 多个同类型的泛型

    /*public <A> void print(A a) {

    System.out.println(a);

    }

    public <A> void print(A a,A b) {

    System.out.println(a);

    System.out.println(b);

    }*/

    public <A> void print(A...a) {

    System.out.println(a);

    }

    A… a 表示方法可以接受多个参数。当调用方法传递多个参数,多个参数被放到a数组中,a是什么类型的数组由开发者调用处传决定。

     泛型接口

    如果接口中的方法参数(形参返回值)确定,可以考虑使用泛型接口形式

    public interface FanInterface<T> {

    public void showInfo(T t);

    }

    实现类能确定泛型接口的类型

    实现类不能确定泛型接口的类型->继续

     泛型的上限和下限 

    public static void print(ArrayList<? extends Pet> list) {

    for (Pet pet : list) {

    pet.showInfo();

    }

    }

    泛型的上限ArrayList(? extends Pet) list 声明了一个容器,容器中的元素类型一定要继承于Pet,我们称这种形式叫做泛型的上限。

    泛型的下ArrayList(? super Pet) list 声明了一个容器容器中的元素类型一定要是Pet的父类我们称这个形式为泛型的下限。

     Set接口

    Set接口表示一个唯一、无序的容器(和添加顺序无关)

     Set接口提供的方法

    public static void main(String[] args) {

    /**

     * :add/addAll

     * :clear/remove/removeAll/retainAll

     * :

     * :contains/containsAll

     * 遍历:iterator

     * 其他:size/isEmpty

     */

    Set<Integer> set = new HashSet<Integer>();

    // [1]添加

    // 无序

    set.add(10);

    set.add(3);

    set.add(20);

    set.add(0);

    // 不能添加重复元素

    boolean r = set.add(1);

    System.out.println(set);

    // 2】删除

    // set.remove(1);

    // set.clear();

    // System.out.println(set);

    // 3】查看是否包含

    System.out.println(set.contains(1));

    // 4】其他

    System.out.println(set.size());

    System.out.println(set.isEmpty());

    }

     Set接口的遍历

    public static void main(String[] args) {

    Set<String> set = new HashSet<String>();

    set.add("banana");

    set.add("apple");

    set.add("coco");

    // 快速遍历

    for (String item : set) {

    System.out.println(item);

    }

    // 迭代器

    Iterator<String> it = set.iterator();

    while(it.hasNext()) {

    String item = it.next();

    System.out.println(item);

    }

    }

    Set接口的实现类常见的有HashSetLinkedHashSetTreeSet

     HashSet

    HashSetSet接口的实现类,底层数据结构是哈希表。

    HashSet是线程不安全的(不保证同步)

     哈希表工作原理

     添加自定义对象

    根据哈希表工作原理,请存储一个自定义对象到HashSet

    package cn.sxt03.hashset;

    public class Student {

    private String id;

    private String name;

    private int age;

    //

    @Override

    public int hashCode() {

    final int prime = 31;

    int result = 1;

    result = prime * result + age;

    result = prime * result + ((id == null) ? 0 : id.hashCode());

    result = prime * result + ((name == null) ? 0 : name.hashCode());

    return result;

    }

    @Override

    public boolean equals(Object obj) {

    if (this == obj)

    return true;

    if (obj == null)

    return false;

    if (getClass() != obj.getClass())

    return false;

    Student other = (Student) obj;

    if (age != other.age)

    return false;

    if (id == null) {

    if (other.id != null)

    return false;

    } else if (!id.equals(other.id))

    return false;

    if (name == null) {

    if (other.name != null)

    return false;

    } else if (!name.equals(other.name))

    return false;

    return true;

    }

    @Override

    public String toString() {

    return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";

    }

    }

    总结

    [1]如果HashSet中存储元素时元素一定要实现hashCode方法和equals方法。

    [2] 优点:添加、删除、查询效率高;缺点:无序

     LinkedHashSet

    LinkedHashSet是Set接口的实现底层数据结构哈希表+链表

    哈希表用于散列元素;链表用于维持添加顺序。

    如果要添加自定义对象元素,也需要重写hashCodeequals方法。

    TreeSet

    TreeSet 是Set接口的实现类,底层数据结构是二叉树。

    TreeSet 存储的数据按照一定的规则存储。存储规则让数据表现自然序。

     TreeSet工作原理

     

    添加一个新元素t存储的步骤

    [1] 如果集合无元素,t直接加入;如果集合有元素,t和根节点比较;

    [2] 如果t小于根节点;把t放到根节点的左子树上;重复1-3步骤

    [3] t大于根节点;把t放到根节点的右子树上;重复1-3步骤

    输出时按照一定的规则:子树->根节点->右子树

    根据TreeSet工作原理,向TreeSet添加自定义元素

    向TreeSet中添加元素时,一定要提供比较策略否则会出现ClassCastException

     

    比较策略分两种:内部比较器外部比较器

    内部比较器

    一个自定义对象实现Comparable并实现compareTo方法通过指定具体的比较策略此时称为内部比较器

    package cn.sxt05.treeset;

    public class Student implements Comparable<Student>{

    private String id;

    private String name;

    private int age;

    // 。。

    @Override

    public String toString() {

    return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";

    }

    @Override

    public int compareTo(Student o) {

    if(this.getAge()<o.getAge()) {

    return -1;

    }else if(this.getAge() == o.getAge()) {

    return 0;

    }else {

    return 1;

    }

    }

    }

    比较策略几种情况

    [1]比较策略一般当前对象写在前面,比较对象也在后面,比较结果默认升序

    return  this.getAge() - o.getAge() ;

    如果想要降序,改变两个比较对象的位置即可。

    [2] 多种比较因素

    @Override

    public int compareTo(Student o) {

    /*if(this.getAge()<o.getAge()) {

    return -1;

    }else if(this.getAge() == o.getAge()) {

    return 0;

    }else {

    return 1;

    }*/

    // return  this.getAge() - o.getAge() ;

    if(this.getAge()<o.getAge()) {

    return -1;

    }else if(this.getAge() == o.getAge()) {

    return this.getName().compareTo(o.getName());

    }else {

    return 1;

    }

    }

     外部比较

    实际开发过程不知道添加元素的源代码无权修改别人的代码此时可以使用外部比较器。

    Comparator 位于java.util包中,定义了compare(o1,o2) 用于提供外部比较策略。

    TreeSet接受一个指定比较策略的构造方法,这些比较策略的实现类必须实现Comparator

    接口

    需求:按照字符串的长度比较

    public class Test01 {

    public static void main(String[] args) {

    LenComparator lenComparator = new LenComparator();

    TreeSet<String> set2 = new TreeSet<String>(lenComparator);

    set2.add("banana");

    set2.add("coco");

    set2.add("apple");

    set2.add("apple");

    System.out.println(set2);

    }

    }

    class LenComparator implements Comparator<String>{

    @Override

    public int compare(String o1, String o2) {

    return o1.length() - o2.length();

    }

    }

    使用匿名内部类优化

    public class Test02 {

    public static void main(String[] args) {

    TreeSet<String> set2 = new TreeSet<String>(new Comparator<String>() {

    @Override

    public int compare(String o1, String o2) {

    return o1.length() - o2.length();

    }

    });

    set2.add("banana");

    set2.add("coco");

    set2.add("apple");

    set2.add("apple");

    System.out.println(set2);

    }

    }

     Map接口

    Map接口称为键值对集合或者映射集合其中的元素(entry)键值对(key-value)的形式存在

    Map 容器接口中提供了增、删、改、查的方式对集合进行操作。

    Map接口中都是通过key来操作键值对,一般key是已知。通过key获取value

     map常用方法

    public static void main(String[] args) {

    /**

     * :put/putAll

     * :clear/remove

     * :put

     * :get/containsKey/containsValue

     * 其他:isEmpty/size

     */

    Map<String, String> map = new HashMap<String,String>();

    // 1put

    map.put("A", "apple");

    map.put("B", "banana");

    map.put("C", "coco");

    // 2】删除

    // map.clear();

    // smap.remove("A");

    // 3】修改

    //map.put("A", "apple x");

    // 4】查看

    String val = map.get("A");

    System.out.println(map.containsKey("D"));

    System.out.println(map);

    }

     map接口的遍历

    通过keySet() 返回mapset集合

    public static void main(String[] args) {

    Map<String, String> map = new HashMap<String,String>();

    map.put("B", "banana");

    map.put("A", "apple");

    map.put("C", "coco");

    // map无序

    // 可以根据key的自然顺序 让map有序  => 一般用string作为key

    System.out.println(map);

    // 遍历

    Set<String> keys = map.keySet();

    for (String key : keys) {

    System.out.println(key+"=>"+map.get(key));

    }

    Iterator<String> it = keys.iterator();

    while(it.hasNext()) {

    String key = it.next();

    System.out.println(key+"=>"+map.get(key));

    }

    }

    Iterator<String> it = keys.iterator();

    while(it.hasNext()) {

    String key = it.next();

    System.out.println(key+"=>"+map.get(key));

    }

    }

    map中以键值对作为元素,键值对map中称为entry,entrySet返回键值对的set集合。

    public static void main(String[] args) {

    Map<String, String> map = new HashMap<String,String>();

    map.put("B", "banana");

    map.put("A", "apple");

    map.put("C", "coco");

    // map无序

    // 可以根据key的自然顺序 让map有序  => 一般用string作为key

    System.out.println(map);

    // entrySet

    Set<Entry<String, String>> entrySet = map.entrySet();

    for (Entry<String, String> entry : entrySet) {

    System.out.println(entry.getKey()+"=>"+entry.getValue());

    }

    Iterator<Entry<String, String>> it2 = entrySet.iterator();

    while(it2.hasNext()) {

    Entry<String, String> entry = it2.next();

    System.out.println(entry.getKey()+"=>"+entry.getValue());

    }

    }

    Map接口的实现类HashMapLinkedHashMapTreeMap

     HashMap

    HashMap 是Map的实现类,keyHashSet存储。

    总结:

    [1] 向HashMap中存储元素时,key一定要实现hashCodeequals

    [2] 一般建议使用String作为Map接口key

     LinkedHashMap

    LinkedHashMapMap接口的实现类,keyLinkedHashSet存储。

    哈希表散列key,链表维持key的添加顺序。

    TreeMap

    TreeMapMap的实现类,keyTreeSet存储。

    public static void main(String[] args) {

    /*TreeMap<String, Object> map = new TreeMap<String,Object>(new Comparator<String>() {

    @Override

    public int compare(String o1, String o2) {

    return o1.length() - o2.length();

    }

    });

    ArrayList<String> list2 = new ArrayList<String>();

    list2.add("ben");

    list2.add("bill");

    map.put("Aa", list2);

    ArrayList<String> list1 = new ArrayList<String>();

    list1.add("alex");

    list1.add("alice");

    list1.add("allen");

    map.put("B", list1);

    System.out.println(map);*/

    TreeMap<Student, Object> map = new TreeMap<Student,Object>(new Comparator<Student>() {

    @Override

    public int compare(Student o1, Student o2) {

    return o1.getAge() - o2.getAge();

    }

    });

    ArrayList<String> list1 = new ArrayList<String>();

    list1.add("alex");

    list1.add("alice");

    list1.add("allen");

    Student s1 = new Student("001", "大狗", 20);

    map.put(s1, list1);

    ArrayList<String> list2 = new ArrayList<String>();

    list2.add("ben");

    list2.add("bill");

    Student s2 = new Student("001", "2", 20);

    // 修改

    map.put(s2, list2);

    System.out.println(map);

    }

                                                Collection集合

                                                        |

                                    1 List 接口          2、Set接口

                                     |(有序可重复)       |(无序 唯一)

            1 ArrayList  2 Vector  3 LinkList          1 HashSet   2  LinkHashSet   3  TreeSet        

  • 相关阅读:
    Java学习 · 初识 多线程
    Java学习 · 初识 IO流
    Java学习 · 初识 容器和数据结构
    Java学习 · 初识 异常机制
    Java学习 · 初识 面向对象深入二
    纯golang爬虫实战-(六)-关于cookiejar的理解 (2020-02-14 13:50)
    纯golang爬虫实战-(五)-登录并带cookie访问
    golang使用gopacket包进行数据包捕获实践(未成功)
    纯go+sqlite3+html/template网站(类似MVC实现数据库CURD、上传下载文件)-最少依赖才是硬道理
    纯golang+sqlite3 CRUD
  • 原文地址:https://www.cnblogs.com/gflb/p/10816113.html
Copyright © 2011-2022 走看看