Java学习(七)泛型与集合


一、泛型

1.泛型定义

泛型是将数据类型参数化,即在编写代码时将数据类型定义成参数,这些类型参数在使用之前再进行指明。
泛型提高了代码的重用性,使得程序更加灵活、安全和简洁。

JDK 5.0之前,为了实现参数类型的任意化,都是通过Object类型来处理,缺点:代码臃肿,需要进行强制类型转换,参数类型必须已知,否则容易引起ClassCastException异常。
JDK 5.0之后,Java增加对泛型的支持,解决以上缺点。泛型经常在类、接口和方法的定义中,分别称为泛型类、泛型接口和泛型方法。

在这里插入图片描述
GenericDemo.java:

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());
    }
}
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.1415);
	dObj.showDataType();
	System.out.println(dObj.getData());
	System.out.println("--------------------------------");
	Generic <Integer> intObj = new Generic <>(123);
	intObj.showDataType();
	System.out.println(intObj.getData());
	System.out.println("--------------------------------");
    }
}

2.泛型的限制

(1)实例化泛型时,类型参数只能是类类型(包括自定义类),如String、Integer等,不能是简单类型。
(2)同一个泛型类可以有多个版本(不同参数类型),不同版本的泛型类的实例是不兼容的,例如Generic 与Generic 的实例是不兼容的。
(3)定义泛型时,类型参数只是占位符,不能直接实例化,例如“new T()”是错误的。
(4)不能实例化泛型数组。
(5)泛型类不能继承Throwable及其子类,即泛型类不能是异常类

二、集合概述

Java的集合类是一些常用的数据结构,如队列、栈、链表等。
Java集合就像一种“容器”,用于存储数量不等的对象,并按照规范实现一些常用的操作和算法。

1.集合框架

Java所有集合类都在java.util包下,
Java集合类主要有两个接口派生而成:Collection和Map,这两个接口是集合框架的根接口
NoteBook.java:

import java.util.ArrayList;
public class NoteBook{
    private ArrayList<String> notes = new ArrayList<String>();//ArrayList是有序列表
    public void add(String s){
	notes.add(s);//添加数据
    }
    public int getSize(){
	return notes.size();//获取数据条数
    }
    public String getNote(int index){
	return notes.get(index);//根据下标找到数据
    }
    public void removeNote(int index){
	notes.remove(index);//删除下标为index的数据
    }
    public String[] list(){
	String a[] = new String[notes.size()];
	for(int i=0;i<notes.size();i++){
	    a[i] = notes.get(i);
	}
	return a;
    }
    public static void main(String[] args){
	NoteBook nb = new NoteBook();
	nb.add("first");
	nb.add("second");
	nb.add("third");
	System.out.println(nb.getSize());
	System.out.println(nb.getNote(1));
	nb.removeNote(1);
	String[] a = nb.list();
	for(String s:a)//获取数组a的每一个值并赋给s
	{
	    System.out.println(s);
	}	
    }
}

使用迭代器后:

import java.util.ArrayList;
import java.util.Iterator;
public class NoteBook{
    private ArrayList<String> notes = new ArrayList<String>();
    public void add(String s){
	notes.add(s);
    }
    public int getSize(){
	return notes.size();
    }
    public String getNote(int index){
	return notes.get(index);
    }
    public void removeNote(int index){
	notes.remove(index);
    }
    public void list(){
	Iterator<String> iterator = notes.iterator();
	while(iterator.hasNext()){
	   System.out.println(iterator.next());
	}	
    }
    public static void main(String[] args){
	NoteBook nb = new NoteBook();
	nb.add("first");
	nb.add("second");
	nb.add("third");
	System.out.println(nb.getSize());
	System.out.println(nb.getNote(1));
	nb.removeNote(1);
	nb.list();
    }
}

两种方式的运行结果一致如下:
(注意:默认下标从0开始)
在这里插入图片描述

2.迭代器接口

迭代器(Iterator):可以采用统一的方式对Collection集合中的元素进行遍历操作该接口是Collection接口的父接口。
方法:
boolean hasNext():判断是否有下一个可访问的对象,有返回true,没有返回false。
E next():返回可访问的下一个元素。
void remove():移除迭代器返回的最后一个元素,该方法必须紧跟在一个元素的访问后执行。

三、集合类

1.Collection接口

Collection接口是Set、Queue和List接口的父接口。该接口中的方法可以操作这三个接口中的任一个集合。由接口的特点可知,其内部的方法都是抽象方法,在应用时需要重写。
在这里插入图片描述
在这里插入图片描述
注意:
(1)add()、addAll()、remove()、removeAll()和retainAll()方法可能会引发不支持该操作的UnsupportedOperationException异常。
(2)将一个不兼容的对象添加到集合中,将产生ClassCastException异常。
(3)Collection接口没有提供获取某个元素的方法,但可以通过iterator()方法获取迭代器来遍历集合中的所有元素
(4)虽然Collection中可以存储任何Object对象,但不建议在同一个集合容器中存储不同类型的对象,建议使用泛型增强集合的安全性,以免引起ClassCastException异常。

2.List 接口及其实现类

List接口:有序、可重复的集合,与数组类似,List集合可以记住每次添加元素的顺序,因此可以根据元素的索引访问List集合中的元素,元素可以重复且长度是可变的(相当于可变长数组)。
ArrayList(数组列表)和Vector(向量)是List接口的两个典型实现类,两者功能类似,推荐使用前者。

ArrayListDemo.java:

import java.util.*;
public class ArrayListDemo{
    public static void main(String[] args){
	ArrayList <String> list = new ArrayList <>();
	//向集合中添加元素
	list.add("北京");
	list.add("上海");
	list.add("天津");
	list.add("济南");
	list.add("青岛");
	//错误,只能添加字符串
	//list.add(1);//错误原因:不同版本的泛型类的实例是不兼容的
	//使用foreach语句遍历
	System.out.println("使用foreach语句遍历");
	for(String e:list){
		System.out.println(e);
	}
	System.out.println("---------------------");
	System.out.println("使用迭代器遍历:");
	//获取ArrayList的迭代器
	Iterator <String> iterator = list.iterator();
	//使用迭代器遍历
	while(iterator.hasNext()){
		System.out.println(iterator.next());
	}
	System.out.println("---------------------");
	//删除下标索引是1的元素,即第二个元素“上海”
	list.remove(1);
	//删除指定元素
	list.remove("青岛");
	System.out.println("删除后剩下的数据:");
	for(String e:list){
		System.out.println(e);
	}
    }
}

运行结果:
在这里插入图片描述

3.Set 接口及其实现类

Set接口:类似一个罐子,将一个对象添加到Set集合时,Set集合无法记住添加的顺序,因此Set集合中的元素不能重复。
常用的实现类:HashSet、TreeSet、EnumSet。
**HashSet:**大多数使用Set集合时都使用该实现类,HashSet使用Hash算法来存储集合中的元素,具有良好的存、取以及可查找性。
**TreeSet:**采用“树”的数据结构来存储集合元素,可保证几何中的元素处于排序状态。
**EnumSet:**专为枚举类设计的集合类,所有元素必须是指定的枚举类型。

HashSetDemo.java:

import java.util.HashSet;
import java.util.Iterator;
public class HashSetDemo{
    public static void main(String[] args){
	HashSet <String> hs = new HashSet <>();
	//向集合中添加元素
	hs.add("北京");
	//添加重复元素
	hs.add("北京");
	hs.add("上海");
	hs.add("天津");
	hs.add("济南");
	hs.add("青岛");
	System.out.println(hs);//以数组形式输出
	//使用foreach语句遍历
	System.out.println("使用foreach语句遍历");
	for(String e:hs){
		System.out.println(e);
	}
	System.out.println("---------------------");
	
	//删除元素
	hs.remove("青岛");
	System.out.println("删除后剩下的数据:");
	Iterator <String> iterator = hs.iterator();
	//使用迭代器遍历
	while(iterator.hasNext()){
		System.out.println(iterator.next());
	}
    }
}

运行结果:
在这里插入图片描述
结果中北京并没有出现在第一位,且仅出现了一次,证明了Set集合无法记住添加的顺序,Set集合中的元素不能重复的特点。

4.Queue 接口及其实现类

Queue接口:以“先进先出(FIFO)”的方式排序各个元素。
Deque(双端队列)是Queue的子接口,LinkedList是Deque和List两个接口的实现类,兼具队列和列表两种特性,是最常使用的集合类之一。

LinkedListDemo.java:

import java.util.LinkedList;
public class LinkedListDemo{
    public static void main(String[] args){
	LinkedList <String> books = new LinkedList <>();
	//在队尾添加元素
	books.offer("Java Web开发技术详解");
	//在队头添加元素
	books.push("数据库原理");
	//在队头添加元素
	books.offerFirst("Java8基础应用与开发");
	//在队尾添加元素
	books.offerLast("C++程序设计");
	System.out.println(books);
	System.out.println("---------------------");
	//使用foreach语句遍历
	System.out.println("使用foreach语句遍历:");
	for(String e:books){
		System.out.println(e);
	}	
    }
}

运行结果:
在这里插入图片描述
注意:经检验知push与offerFirst等价,都可以实现将数据插入开头;offer与offerLast等价,都是将数据插入末尾。

5.Map 接口及其实现类

Map接口:以key-value键值对映射关系存储的集合,可以根据每个元素的key来访问对应的value,Map集合中的key不允许重复,value可以重复。key-value键值对映射关系的示意图如下所示。

在这里插入图片描述

Map接口的两个实现类:
HashMap:基于哈希算法的Map接口的实现类,该实现类提供所有映射操作,并允许使用null键和null值,但不能保证映射的顺序,即是无序的映射集合
TreeMap:基于“树”接口来存储的Map接口实现类,可以根据键的自然顺序进行排序,或定制排序方式。在使用TreeMap时,不允许使用null键和null值,当使用get()方法获取元素时,没有指定的键时会返回null。

在这里插入图片描述
在这里插入图片描述
HashMapDemo.java:

import java.util.HashMap;
public class HashMapDemo{
    public static void main(String[] args){
	HashMap <Integer,String> hm = new HashMap <>();
	//添加数据,key-value键值对形式
	hm.put(1,"张三");
	hm.put(2,"李四");
	hm.put(3,"王二麻子");
	hm.put(4,"赵五");
	hm.put(5,"刘六");
	hm.put(null,null);
	//根据key值获取value
	System.out.println(hm.get(1));
	System.out.println(hm.get(3));
	System.out.println(hm.get(5));
	System.out.println(hm.get(null));

	//根据key删除
	hm.remove(1);

	//key为1的元素已经删除,返回null
	System.out.println(hm.get(1));	
    }
}

TreeMapDemo.java:

import java.util.TreeMap;
public class TreeMapDemo{
    public static void main(String[] args){
	TreeMap <Integer,String> tm = new TreeMap <>();
	//添加数据,key-value键值对形式
	tm.put(1,"张三");
	tm.put(2,"李四");
	tm.put(3,"王二麻子");
	tm.put(4,"赵五");
	tm.put(5,"刘六");
	//错误,不允许null键和null值
	//tm.put(null,null);
	//根据key值获取value
	System.out.println(tm.get(1));
	System.out.println(tm.get(3));
	System.out.println(tm.get(5));
	//错误,不允许null键和null值
	//System.out.println(tm.get(null));

	//根据key删除
	tm.remove(1);

	//key为1的元素已经删除,返回null
	System.out.println(tm.get(1));	
    }
}

四、集合转换(了解)

Map集合可以转换为Collection集合,方法:
entrySet():返回一个包含了Map中元素的集合,每个元素都包括键和值。
keySet():返回Map中所有键的集合。
values():返回Map中所有值的集合。

MapChangeCollectionDemo.java:

import java.util.*;
import java.util.Map.Entry;
public class MapChangeCollectionDemo{
    public static void main(String[] args){
	HashMap <Integer,String> hm = new HashMap <>();
	//添加数据,key-value键值对形式
	hm.put(1,"张三");
	hm.put(2,"李四");
	hm.put(3,"王二麻子");
	hm.put(4,"赵五");
	hm.put(5,"刘六");
	//使用entrySet()方法获取Entry键值对集合,Map.Entry是Map声明的一个内部接口,此接口为泛型,定义为Entry。它表示Map中的一个实体(一个key-value对)。接口中有getKey(),getValue方法。
	Set<Entry <Integer,String>> set = hm.entrySet();
	System.out.println("所有Entry:");
	//遍历所有元素
	for(Entry <Integer,String> entry:set){
		System.out.println(entry.getKey()+":"+entry.getValue());
	}
	System.out.println("-----------------");

	//使用keySet()方法获取所有键的集合
	Set <Integer> keySet = hm.keySet();
	System.out.println("所有key:");
	for(Integer key:keySet){
		System.out.println(key);
	}
	System.out.println("-----------------");

	//使用values()方法获取所有值的集合
	Collection <String> valueSet = hm.values();
	System.out.println("所有value:");
	for(String value:valueSet){
		System.out.println(value);
	}

    }
}

五、集合工具类(了解)后期扩展

Java集合框架汇总还提供了两个辅助工具类:Collections和Arrays。
Collections工具类:提供了一些对Collection集合常用的静态方法,如排序、复制、查找以及填充等操作。
Arrays工具类:提供了针对数组的各种静态方法,如排序、复制、查找等操作。


总结

本章重点掌握前三个知识点,泛型是将数据类型参数化,提高了代码的重用性。集合类分别讲了Collection接口下的三个常用子接口:List=>ArrarList(下标从0开始,可重复);Set=>HashSet(HashSet使用Hash算法来存储集合中的元素,具有良好的存、取以及可查找性,无序不可重复);Queue=>LinkedList(先进先出队列,push=offerFirst,offer=offerLast)。Map接口:Map=>HashMap(有键值对,key值不可以重复,value值可以重复,无序,键值对可以为null)。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

君知燕云归

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值