咳咳,本篇来讲解下集合和泛型
这个知识点也是很重要的哦
大家耐心点儿
集合:
我们之前讲到
如果要存放多个对象,可以使用数组,但是数组有局限性
比如 声明长度是10的数组
不用的数组就浪费了
超过10的个数,又放不下
然而,“集合”就不用担心这些问题
集合有很多种
下面我们来一一讲解
泛型:
泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?
顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
一、ArrayList
ArrayList 是一个数组队列,相当于 动态数组。与Java中的数组相比,它的容量能动态增长。它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口。
代码演示:
package com.baidu.demo.test10;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
public class Demo1 {
public static void main(String[] args) {
//ArrayList实现了接口List 常见的写法会把引用声明为接口List类型
//<>指的就是泛型 我这里写的是Integer 也就是说这个集合就只能存放Integer类型的东西
List<Integer> l = new ArrayList<Integer>();
//添加内容
l.add(1);
l.add(2);
l.add(3);
System.out.println("==================================");
//遍历的方式一 普通for遍历
//size()就是获取集合的大小
for(int i = 0;i < l.size();i++) {
//使用get获取集合的内容
System.out.println(l.get(i));
}
System.out.println("==================================");
//遍历的方式二 使用迭代器Iterator遍历集合中的元素
//使用迭代器的好处是 遍历容器中的每个对象而不用考虑容器中对象的个数,而且保护数据不显示的表现出来。
//迭代遍历方式一
Iterator<Integer> it = l.iterator();
while (it.hasNext()) {
//it.next的意思就是获取到当前对象
System.out.println(it.next());
}
System.out.println("***********************");
//迭代遍历方式二
for(Iterator<Integer> iterator = l.iterator();iterator.hasNext();) {
System.out.println(iterator.next());
}
System.out.println("==================================");
//遍历的方式三 增强型for遍历
for(Integer i : l) {
System.out.println(i);
}
}
}
运行结果:
二、LinkedList
LinkedList简介
LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。
LinkedList 实现 List 接口,能对它进行队列操作。
LinkedList 实现 Deque 接口,即能将LinkedList当作双端队列使用。
LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。
LinkedList 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。
LinkedList 是非同步的。
代码演示:
package com.baidu.demo.test10;
import java.util.LinkedList;
public class Demo2 {
public static void main(String[] args) {
//与ArrayList一样,LinkedList也实现了List接口,诸如add,remove,contains等等方法 这里我就只演示下特殊的地方了
LinkedList<Integer> l = new LinkedList<Integer>();
//双向链表 - Deque
//在最后插入
l.addLast(1);
l.addLast(2);
l.addLast(3);
//在最前面插入
l.addFirst(0);
//查看全部
System.out.println(l);
//查看最前面
System.out.println(l.getFirst());
//查看最后面
System.out.println(l.getLast());
System.out.println("============================");
//队列 - Queue
/*
* LinkedList 除了实现了List和Deque外,还实现了Queue接口(队列)。
*Queue是先进先出队列 FIFO,常用方法:
*offer 在最后添加元素
*poll 取出第一个元素
*peek 查看第一个元素
*/
//在最后添加元素
LinkedList<String> l2 = new LinkedList<String>();
l2.offer("一");
l2.offer("二");
l2.offer("三");
//取出第一个元素 FIFO 先进先出
//取出第一个元素后第一个元素就被去除了
System.out.println("被取出的内容:"+l2.poll());
System.out.println("取出后的队列:"+l2);
//查看第一个元素 不会被去除哦
System.out.println("查看第一个元素:"+l2.peek());
}
}
运行结果:
三、HashMap和HashSet
HashMap简介:
HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
HashMap 继承于AbstractMap,实现了Map、Cloneable、java.io.Serializable接口。
HashMap 的实现不是同步的,这意味着它不是线程安全的。它的key、value都可以为null。此外,HashMap中的映射不是有序的
HashSet简介:
HashSet类实现了Set接口,由一个实际上是HashMap实例的散列表支持。不能保证该集合的迭代次序,这意味着该类不能保证元素随时间的不变顺序。这个类允许null元素。由于它实现了Set接口,所以不允许重复值。
代码演示:
package com.baidu.demo.test10;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
public class Demo3 {
public static void main(String[] args) {
//声明一个HashMap 它包含了键和值 这里我设置了泛型 键的泛型为Integer 值的泛型为String
HashMap<Integer, String> h = new HashMap<Integer, String>();
//设置它的内容
h.put(1, "一");
h.put(2, "二");
h.put(3, "三");
//键不能重复,值可以重复哦
h.put(4, "三");
//打印所有键值
System.out.println(h);
//打印键为1的值
System.out.println(h.get(3));
System.out.println("===========================================");
//声明一个HashSet
/*
* Set中的元素,不能重复
* Set中的元素,没有顺序。 严格的说,是没有按照元素的插入顺序排列
*/
HashSet<Integer> hs = new HashSet<Integer>();
hs.add(4);
hs.add(2);
hs.add(3);
//打印HashSet 可以发现它不是按照插入的顺序进行排序的
System.out.println(hs);
//HashSet的遍历
//Set不提供get()来获取指定位置的元素 所以遍历需要用到迭代器,或者增强型for循环
//遍历方式一
for(Iterator<Integer> iterator = hs.iterator();iterator.hasNext();) {
System.out.println(iterator.next());
}
System.out.println("*****************************");
//遍历方式二
for(Integer i : hs) {
System.out.println(i);
}
}
}
运行结果:
四、Collection
Collection是 Set List Queue和 Deque的接口
Queue: 先进先出队列
Deque: 双向链表
注:Collection和Map之间没有关系,Collection是放一个一个对象的,Map 是放键值对的
注:Deque 继承 Queue,间接的继承了 Collection
五、Collections
Collections是一个类,容器的工具类,就如同Arrays是数组的工具类
代码演示:
package com.baidu.demo.test10;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Demo4 {
public static void main(String[] args) {
List<Integer> l = new ArrayList<Integer>();
//在ArrayList中添加八个数字
for (int i = 0; i < 8; i++) {
l.add(i);
}
System.out.println("集合中的数据:"+l);
//翻转集合
Collections.reverse(l);
System.out.println("集合翻转后的数据:"+l);
//混淆集合
Collections.shuffle(l);
System.out.println("集合混淆后的数据:"+l);
//排序集合
Collections.sort(l);
System.out.println("集合排序后的数据:"+l);
//交换集合中两个数据的位置 这里把下标为2的数据和下标为7的数据交换
Collections.swap(l, 2, 7);
System.out.println("集合交换后的数据:"+l);
//滚动集合 这里把数据向右滚动两位
//滚动前先进行重新的一个从小到大的排序
Collections.sort(l);
Collections.rotate(l, 2);
System.out.println("集合滚动后的数据:"+l);
//把非线程安全的集合转化成线程安全的 这里把上面的l集合转化成线程安全的集合 线程安全之后我会讲 现在你们只需要知道有这么个东西就行
List<Integer> ll = Collections.synchronizedList(l);
}
}
运行结果:
六、泛型基本讲解
使用泛型的好处:
泛型的用法是在容器后面添加< Type>
Type可以是类,抽象类,接口
如果Type是String型的 则只能放String类型的数据 别的不行
设计泛型类:
设计类的时候,在类的声明上,加上一个,表示该类支持泛型。
T是type的缩写,也可以使用任何其他的合法的变量,比如A,B,X都可以,但是一般约定成俗使用T,代表类型。
泛型中通配符的使用:
ArrayList<? extends xxx> heroList = ............
上面代码中的“? extends xxx” 表示这是一个xxx泛型或者其子类泛型
ArrayList<? super xxx> heroList = .................
上面代码中的“? super xxx” 表示这是一个xxx泛型或者其父类泛型
泛型通配符? 代表任意泛型
既然?代表任意泛型,那么换句话说,这个容器什么泛型都有可能
所以只能以Object的形式取出来
并且不能往里面放对象,因为不知道到底是一个什么泛型的容器
好啦
关于集合和泛型的讲解先到这儿吧