Java中的泛型与集合

欢迎关注我的公众号【软件大爆炸】
Java学习中的碎碎念
Java中易忽略的基础知识
Java面向对象基础
Java中的核心类
Java抽象类和接口
Java中的异常
Java中的泛型与集合
泛型类是引用类型,在堆内存中。
先看一段代码

public class GenericDemo {
    
    
    public static void main(String[] args) {
    
    
        //这些类型参数在使用之前再进行指明。
        Generic<String> strObj = new Generic<String>("欢迎关注公众号软件大爆炸!");
        strObj.showDataType();
        System.out.println(strObj.getData());
        System.out.println("__________________________");

        Generic<Double> dObj = new Generic<>(3.14);//这些类型参数在使用之前再进行指明。
        dObj.showDataType();
        System.out.println(dObj.getData());
        System.out.println("____________________________");

        Generic<Integer> iObj = new Generic<>();
        iObj.setData(100);//这些类型参数在使用之前再进行指明。
        iObj.showDataType();
        System.out.println(iObj.getData());
    }
}

class Generic<T>{
    
    //在编写代码时将数据类型定义成参数
    private T data;

    public Generic(){
    
    
    }

    public Generic(T data){
    
    
        this.data = data;
    }

    public T getData() {
    
    
        return data;
    }

    public void setData(T data) {
    
    
        this.data = data;
    }

    public void showDataType(){
    
    
        System.out.println("数据的类型是:"+data.getClass().getName());
    }
}
数据的类型是:java.lang.String
欢迎关注公众号软件大爆炸!
__________________________
数据的类型是:java.lang.Double
3.14
____________________________
数据的类型是:java.lang.Integer
100

Process finished with exit code 0

接下来进行一些简单的说明

  • 泛型是将数据类型参数化,即在编写代码时将数据类型定义成参数,这些类型参数在使用之前再进行指明。
    例如,类的定义为:class Generic<T>,使用时(即实例化时):Generic<String> strObj = new Generic<String>("欢迎关注公众号软件大爆炸!");或者Generic<Integer> iObj = new Generic<>();iObj.setData(100);。并且类型参数只是占位符一般使用大写的“T”、“U”、“V”等作为类型参数
  • 从Java7开始,实例化泛型类时只需给出一对尖括号“<>”即可,Java可以推断尖括号中的泛型信息。将两个尖括号放在一起像一个菱形,因此也被称为“菱形语法
    例如:Generic<Double> dObj = new Generic<>(3.14);,其实就等价于Generic<Double> dObj = new Generic<Double>(3.14);

下面介绍一下关于通配符:
通配符指

public class NoWildcardDemo {
    
    
    public static void main(String[] args) {
    
    
        //Right
        Generic<Object> gObbj = new Generic<Object>("Object");
        myMethod(gObbj);
        //Wrong
//        Generic<Integer> gint = new Generic<>(12);
//        myMethod(gint);
        //Wrong
//        Generic<Double> gdbl = new Generic<>(3.145);
//        myMethod(gdbl);
    }

    public static void myMethod(Generic<Object> g){
    
    
        g.showDataType();
    }
}

上面的代码出错的原因就在于没有使用通配符,所以只能使用Object,如果将public static void myMethod(Generic<Object> g)改成public static void myMethod(Generic<?> g),则不再报错,如下:

public class NoWildcardDemo {
    
    
    public static void main(String[] args) {
    
    
        //Right
        Generic<Object> gObbj = new Generic<Object>("Object");
        myMethod(gObbj);
        //Right
        Generic<Integer> gint = new Generic<>(12);
        myMethod(gint);
        //Right
        Generic<Double> gdbl = new Generic<>(3.145);
        myMethod(gdbl);
    }

    public static void myMethod(Generic<?> g){
    
    
        g.showDataType();
    }
}
数据的类型是:java.lang.String
数据的类型是:java.lang.Integer
数据的类型是:java.lang.Double

关于有界类型

  • 上界:使用extends关键字。
  • 下界:使用super关键字。
    上界的举例:
public class UpBoundGenericDemo {
    
    
    public static void main(String[] args) {
    
    
        Generic<Integer> gint = new Generic<>(12);
        myMethod(gint);

        Generic<Double> gdbl = new Generic<>(3.14);
        myMethod(gdbl);

        Generic<String> gstr = new Generic<>("String");
        //Wrong code
//        myMethod(gstr);
    }
    public static void myMethod(Generic<? extends Number> g){
    
    
        g.showDataType();
    }
}

class UpBoundGeneric<T extends Number>{
    
    
    private T data;

    public UpBoundGeneric(){
    
    
    }

    public UpBoundGeneric(T dara){
    
    
        this.data = data;
    }

    public T getData(){
    
    
        return data;
    }

    public void setData(T data){
    
    
        this.data = data;
    }

    public void showDataType(){
    
    
        System.out.println("数据的类型是:"+data.getClass().getName());
    }
}
数据的类型是:java.lang.Integer
数据的类型是:java.lang.Double

Process finished with exit code 0

下界的举例:

public class LowBoundGenericDemo {
    
    
    public static void main(String[] args) {
    
    
        Generic<String> gstr = new Generic<>("String类本身");
        myMethod(gstr);

        Generic<Integer> gint = new Generic<>(5);
        //Wrong code
//        myMethod(gint);
    }
    
    public static void myMethod(Generic<? super String> g){
    
    
        g.showDataType();
    }
}
数据的类型是:java.lang.String

Process finished with exit code 0

关于Java集合

  • 集合类使程序员不用考虑数据结构和算法实现的细节。提高了开发效率。
    Java集合主要由Collection和Map这两个接口派生。
    在这里插入图片描述
    在这里插入图片描述
  • Set接口:无序、不可重复的集合
  • Queue接口:队列集合
  • List接口:有序、可以重复的集合
  • Map保存的数据都是由Key/Value对组成的。

List的子类有ArrayListVector。两者的区别在于前者是非线程安全的,后者是线程安全的。
ArrayList可以通过Collections工具类手动变成线程安全的。
下面演示ArrayList的使用:

import java.util.ArrayList;
import java.util.Iterator;

public class ArrayListDemo {
    
    
    public static void main(String[] args) {
    
    
        ArrayList<String> list = new ArrayList<>();
        //向列表中添加元素
        list.add("郑州");
        list.add("北京");
        list.add("上海");
        list.add("深圳");
        //使用for...each循环
        for (String e: list
             ) {
    
    
            System.out.println(e);
        }
        System.out.println("----------------------");
        //使用迭代器遍历
        Iterator<String> iterator = list.iterator();
        while(iterator.hasNext()){
    
    
            System.out.println(iterator.next());
        }
        System.out.println("----------------------");
        list.remove("上海");
        for (String e: list
        ) {
    
    
            System.out.println(e);
        }
    }
}
郑州
北京
上海
深圳
----------------------
郑州
北京
上海
深圳
----------------------
郑州
北京
深圳

Process finished with exit code 0

下面演示Vector的使用:

import java.util.Iterator;
import java.util.Stack;
import java.util.Vector;

public class VectorStackDemo {
    
    
    public static void main(String[] args) {
    
    
        Vector<Integer> v = new Vector<>();
        for (int i = 0; i < 5; i++) {
    
    
            v.add(i);
        }
        System.out.println("Vector中的元素:");
        show(v.iterator());
        System.out.println("-------------------------");
        v.remove(2);
        System.out.println("Vector删除后剩下的数据");
        show(v.iterator());
        System.out.println("-------------------------");

        Stack<String> s = new Stack<>();
        for (int i = 0; i <15; i++) {
    
    
            s.push(String.valueOf(i));
        }
        System.out.println("Stack中的元素:");
        show(s.iterator());
        System.out.println("-----------------------");
        System.out.println("Stack出栈:");
        while(!s.isEmpty()){
    
    
            System.out.println(s.pop());
        }
    }

    public static void show(Iterator<?> iterator){
    
    
        while (iterator.hasNext()) {
    
    
            System.out.println(iterator.next());
        }
    }
}

Vector中的元素:
0  1  2  3  4  
-------------------------
Vector删除后剩下的数据
0  1  3  4  
-------------------------
Stack中的元素:
0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  
-----------------------
Stack出栈:
14  13  12  11  10  9  8  7  6  5  4  3  2  1  0  
Process finished with exit code 0


关于Set集合:
Set接口常用的实现类包括 HashSetTreeSetEnum set,这三个实现类各具特色

  • HashSetSet接口的典型实现类,大多数使用Set集合时都使用该实现类HashSet使用Hash算法来存储集合中的元素,具有良好的存、取以及可查找性。
  • Treeset采用Tree“树”的数据结构来存储集合元素,因此可以保证集合中的元素处于排序状态。 Treeset支持两种排序方式:自然排序和定制排序,默认情况下采用自然排序
  • Enum Set是一个专为枚举类设计的集合类,其所有元素必须是指定的枚举类型。Enum Set集合中的元素也是有序的,按照枚举值顺序进行排序。
//HashSet Demo
import java.util.HashSet;

public class HashDemo {
    
    
    public static void main(String[] args) {
    
    
        //使用泛型HashSet
        HashSet<String> hs = new HashSet<>();
        //向HashSet中添加元素
        hs.add("one");
        hs.add("two");
        hs.add("three");
        //直接输出HashSet对象
        System.out.println("开始的元素有:"+hs);
        hs.remove("one");
        System.out.println("剩下的元素是:"+hs);
    }
}
开始的元素有:[one, two, three]
剩下的元素是:[two, three]

Process finished with exit code 0
//TreeSet Demo
import java.util.TreeSet;

public class TreeSetDemo {
    
    
    public static void main(String[] args) {
    
    
        TreeSet<String> hs = new TreeSet<>();
        hs.add("1");
        hs.add("4");
        hs.add("2");
        hs.add("3");
        System.out.println(hs);
        hs.remove("2");
        System.out.println(hs);
    }
}

[1, 2, 3, 4]
[1, 3, 4]

Process finished with exit code 0
import java.util.LinkedList;

public class LinkedListDemo {
    
    
    public static void main(String[] args) {
    
    
        LinkedList<String> names = new LinkedList<>();
        //在队表末尾添加元素
        names.offer("John");
        //在队头添加元素
        names.push("Bob");
        //在队头添加元素
        names.offerFirst("Lili");
        //在队表末尾添加元素
        names.offerLast("Steve");
        System.out.println(names);

        //访问栈顶元素(没有删除)
        System.out.println("栈顶元素是:"+names.peekFirst());
        //访问末尾元素(没有删除)
        System.out.println("末尾元素是:"+names.peekLast());
    }
}
[Lili, Bob, John, Steve]
栈顶元素是:Lili
末尾元素是:Steve

Process finished with exit code 0
import java.util.ArrayDeque;

public class ArrayDequeDemo {
    
    
    public static void main(String[] args) {
    
    
        ArrayDeque<String> queue = new ArrayDeque<>();
        //在队尾添加元素
        queue.offer("公众号软件大爆炸");
        //在队头添加元素
        queue.push("注重分享");
        System.out.println(queue);

        //从队首获取元素,同时获取的这个元素将从原队列删除
        queue.poll();
        System.out.println(queue);
    }
}
[注重分享, 公众号软件大爆炸]
[公众号软件大爆炸]

Process finished with exit code 0

关于Map

  • HashMap是基于哈希算法的Map接口的实现类,该实现类提供所有映射操作,并允许使用nul键和null值,但不能保证映射的顺序,即是无序的映射集合;
  • TreeMap是基于“树”结构来存储的Map接口实现类,可以根据其键的自然顺序进行排序,或定制排序方式。

首先演示HashMap

//HashMap Demo
import java.util.HashMap;

public class HashMapDemo {
    
    
    public static void main(String[] args) {
    
    
        HashMap<Integer, String> hm = new HashMap<>();
        hm.put(1, "zhengzhou");
        hm.put(2, "beijing");
        hm.put(3, "shenzhen");
        hm.put(4, "hangzhou");
        hm.put(null, null);
        System.out.println(hm.get(1));
        System.out.println(hm.get(4));
        hm.remove(1);
        System.out.println(hm.get(1));
    }
}

下面演示TreeMap

//TreeDemo
zhengzhou
hangzhou
null

Process finished with exit code 0
import java.util.TreeMap;

public class TreeMapDemo {
    
    
    public static void main(String[] args) {
    
    
        TreeMap<Integer, String> tm = new TreeMap<>();
        tm.put(1, "zhengzhou");
        tm.put(2, "beijing");
        tm.put(3, "hangzhou");
        //Wrong code//不允许使用Null键和null值
//        tm.put(null, null);
        System.out.println(tm.get(2));
        tm.remove(2);
        //Wright code
        System.out.println(tm.get(2));
    }
}
beijing
null

Process finished with exit code 0

猜你喜欢

转载自blog.csdn.net/weixin_44895666/article/details/107316432