泛型类是引用类型,在堆内存中。

先看一段代码

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这两个接口派生。
    Java中的泛型与集合_HashMap
    Java中的泛型与集合_HashMap_02
  • Set接口:无序、不可重复的集合
  • Queue接口:队列集合
  • List接口:有序、可以重复的集合
  • Map保存的数据都是由Key/Value对组成的。

List的子类有​​ArrayList​​和​​Vector​​。两者的区别在于前者是非线程安全的,后者是线程安全的。

​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接口常用的实现类包括 ​​HashSet​​、 ​​TreeSet​​和 ​​Enum set​​,这三个实现类各具特色


  • ​HashSet​​​是​​Set​​​接口的典型实现类,大多数使用​​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