集合框架&泛型

集合框架&泛型

集合

一个长度可以改变、可以保持任意数据类型的动态数组

接口

接口 功能
Collection 集合框架最基础的接口、最顶层的接口
List Collection的子接口、存储有序、不唯一(元素可重复)的对象、最常用的接口
Set Collection的子接口、存储无序、唯一(元素不可重复)的对象
Map 独立于Collection的另一个接口、最顶层的接口、存储一组键值对、提供键到值的映射
lerator 输出集合元素的接口、一般适用于无序集合、从前往后输出
Listterator lterator子接口、可以双向输出集合中的元素
Enumeration 传统的输出接口、已经被lterator取代
SortedSet Set的子接口、可以对集合中的元素进行排序
Queue 队列接口
Map.Entry Map的内部接口、描述Map中存储的一组键值对元素

Collection接口

最基础的父接口、可以存储一组无序、不唯一的对象
是Lterable接口的子接口

Collection接口常用方法

方法 功能
int size() 获取集合长度
boolean isEmpty() 判断集合中是否存在某个对象
Iterator iterator() 实例化Iterator接口、遍历集合
Object[] toArray() 将集合转换为一个Object数组
T[] toArray(T[] a) 将集合转换为一个指定数据类型的数组
boolean add(E e) 向集合中添加元素
boolean reomove(Object o) 从集合中删除元素
boolean containsAll(Collection c) 判断集合中是否存在另一个集合的所有元素
boolean addAll(Collection c) 向集合中添加某个集合的所有元素
boolean removeAll(Collection c) 从集合中删除某个集合的所有元素
void clear() 清除集合中的所有元素
boolean equals(Collection c) 判断两个集合是否相等
int hashCode() 返回集合的哈希值

Collection子接口

list:存放有序、不唯一的元素
Set:存放无序、唯一的元素
Queue:队列接口

List接口扩展方法

方法 功能
T get(int index) 通过下标返回集合中对应位置的元素
T Set(int index, T element 在集合中的指定位置存入对象
int indexOf(Object o) 从前向后查找某个对象在集合中的位置
int lastIndexOf(Object o) 从后向前查找某个对象在集合中的位置
ListLterator ListLterator() 实例化ListLterator接口、用来遍历List集合
List subList(int fromIndex, int toIndex) 通过下标截取List集合

List接口的实现类

ArrayList:基于数组的实现、非线程安全、效率高、所有的方法都没有synchronized修饰
Vector:线程安全、效率低、实现线程安全直接通过synchronized修饰方法来完成
Stack:Vector的子类、实现了栈的数据结构、后进先出
LikedList:实现先进先出对列、采用链表形式存储

Stack操作栈的方法

  • push:入栈方法
  • peek: 取出栈顶元素、将栈顶复制一份取出、去完之后栈内的数据结构不变
  • pop: 取出栈顶元素、直接取出栈顶元素、取完之后站内数据减一

ArrayList和LikedList的区别

内存中存储的形式不同、ArrayList采用的是数组的方式、LikedList采用的是链表的形式
数组在内存中的存储空间是连续的、读取快、增删慢
因为数组在内存中是连续的、所以数据可以通过寻址公式很快的找到目标元素的内存地址、因为内存是连续的、所以新增或删除元素、必然需要移动数据、而且数组长度越长、需要移动的元素越多、所以操作越慢
链表在内存中存储空间是不连续的,读取慢,增删快
链表在内存中是不连续的、没有固定的公式可以使用、要读取只能从第一位开始一直遍历目标元素、数据规模越大、操作越慢
增删快、因为只需要重新设置目标元素前后两个结点的后置指针即可、与数据规模无关

LinkedList和Stack的pop方法区别

相同点:都是取出集合中第一个元素
不同点:两者的顺序是相反的、Stack是后进先出原则、所以pop方法取出的是最后一个元素、LinkedList是先进先出原则、所以pop方法取出的是第一个元素

Set

Set是Collection的子接口、Set集合是以散列的形式存储数据、所以元素是没有顺序的、可以存储一组无序且唯一的数据

Set常用实现类

HashSet

存储一组无序且唯一的对象
无序:元素的存储顺序和遍历顺序不一致

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static void main(String[] args) {
HashSet hashSet = new HashSet();

hashSet.add("Hellol");
hashSet.add("World");
hashSet.add("xiaobo");
hashSet.add("wyb");
hashSet.add("xiaobo");

System.out.println(hashSet);
System.out.println("长度为:" + hashSet.size());

//遍历
Iterator iterator = hashSet.iterator();
//游标下一个如果不为空则为真
while (iterator.hasNext()){
//移动游标
System.out.println(iterator.next());
}
}

LinkedHashSet

存储一组有序且唯一的元素
有序:元素的存储顺序和遍历顺序一致

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static void main(String[] args) {
LinkedHashSet hashSet = new LinkedHashSet();

hashSet.add("Hellol");
hashSet.add("World");
hashSet.add("xiaobo");
hashSet.add("wyb");
hashSet.add("xiaobo");

System.out.println(hashSet);
System.out.println("长度为:" + hashSet.size());

//遍历
Iterator iterator = hashSet.iterator();
//游标下一个如果不为空则为真
while (iterator.hasNext()){
//移动游标
System.out.println(iterator.next());
}
}

LinkedHashSet 如何判断两个对象是否相等

首先会判断两个对象的 hashCode 是否相等
如果不相等、则认为不是同一个对象
如果相等、在进行equals判断、equals相等、则两对象相等、否则不等

什么是HashCode

将对象的内部信息、通过某种特定规则转换成一个散列值、就是该对象的 hashCode

TreeSet

存储一组有序且唯一的数据
有序:集合内部自动对所有的元素按照升序进行排列、无论存入的顺序是什么、遍历的时候都一定按照升序输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public static void main(String[] args) {
TreeSet treeSet = new TreeSet();
treeSet.add(new Data(6));
treeSet.add(new Data(5));
treeSet.add(new Data(3));
treeSet.add(new Data(4));
treeSet.add(new Data(2));
treeSet.add(new Data(6));
treeSet.add(new Data(1));

Iterator iterator = treeSet.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
class Data implements Comparable{

private int num;

public Data(int num){
this.num = num;
}

//instanceof判断是否是为一个类型
//对象o是否为Data类型
/**
* 返回值:
* 1 表示A大于B
* 0 表示A等于B
* -1 表示A小于B
*/
@Override
public int compareTo(Object o) {
if(o instanceof Data){
Data data = (Data) o;
if (this.num > data.num){
return 1;
}else if(this.num == data.num){
return 0;
}else{
return -1;
}
}
return 0;
}
@Override
public String toString() {
return "Data{" +
"num=" + num +
'}';
}
}

Map

Map 可以操作一对元素、因为 Map 存储结构是 key - value 映射/
Map接口定义时使用了泛型、并且定义了两个泛型K和V、K表示Key键、V表示value值

Map常用的方法

方法 描述
int size() 获取集合长度
boolean isEmpty() 判断集合是否为空
boolean containsKey(Object key) 判断集合中是否存在某个 key
boolean containsValue(Object value) 判断集合中是否存在某个 value
V get(Object key) 取出集合中 key 对应的 value
V put(K key,V value) 向集合中存入一组 key-value 的元素
V remove(Object key) 删除集合中 key 对应的 value
void putAll(Map map) 向集合中添加另外一个 Map
void clear() 清除集合中所有的元素
Set《k》 keySet() 取出集合中所有的 key,返回一个 Set
Collection《v》 values() 取出集合中所有的 value,返回一个 Collection
int hashCode() 获取集合的散列值
boolean equals(Object o) 比较两个集合是否相等

Map接口的实现类

hashMap

存储一组无序、key不可以重复、value可以重复的元素
非线程安全的、性能高

hashtable

存储一组无序、key不可以重复、value可以重复的元素
线程安全的、性能低

TreeMap

存储一组有序、key不可以重复、value可以重复的元素、可以按照key进行排序

Collections 工具类

专门提供一些对集合的操纵、Collections针对集合的工具类
Arrays针对数组的工具类

Collection工具类的常用方法

方法 描述
public static sort() 对集合进行排序
public static int binarySearch(List list,Object v) 查找 v 在 list 中的位置,集合必须是生序排列
public static get(List list,int index) 返回 list 中 index 位置的值
public static void reverse(List list) 对 list 进行反序输出
public static void swap(List list,int i,int j) 交换集合中指定位置的两个元素
public static void fill(List list,Object obj) 将集合中所有元素替换成 obj
public static Object min(List list) 返回集合中的最小值
public static Object max(List list) 返回集合中的最大值
public static boolean replaceAll(List list,Object old,Object new) 在 list 集合中用 new 替换 old
public static boolean addAll(List list,Object… obj) 向集合中添加元素

Object…可变参数

1
2
3
public static void test(Object... arg){

}

参数可以是任意个数、但是类型必须匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
Collections.addAll(arrayList,
new Student(1,"小博",21),
new Student(2,"小张",22),
new Student(3,"小金",24)
);
Collections.sort(arrayList);
System.out.println(arrayList);
}
class Student implements Comparable {

private int id;
private String name;
private int age;

public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}

@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Object o) {
if (o instanceof Student) {
Student student = (Student) o;
if (this.age > student.age) {
return -1;
} else if (this.age == student.age) {
return 0;
} else {
return 1;
}
}
return 0;
}
}

集合框架

泛型(Generics)

在类定义时不指定类中信息的具体数据类型、而是暂时用一个标识来替代、当外部实例化对象时再来指定具体的数据类型

直接定义

1
2
3
4
5
6
7
public class A{
private B b;

public C test(D d){
return new C();
}
}

泛型定义

1
2
3
4
5
6
7
public class A<T,E,M>{
private T b;
public E test(M m){
return E;
}
}
A<B,C,D> a = new A();

使用泛型的优点

极大地提升程序的灵活性、提升类的扩展性
可以指代成员变量类型、方法的参数类型、方法的返回值类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class Time<H,M,S> {

private H hour;
private M minute;
private S second;

public H getHour() {
return hour;
}

public void setHour(H hour) {
this.hour = hour;
}

public M getMinute() {
return minute;
}

public void setMinute(M minute) {
this.minute = minute;
}

public S getSecond() {
return second;
}

public void setSecond(S second) {
this.second = second;
}
}
public static void main(String[] args) {
Time<Integer,Integer,Double> time = new Time<>();
time.setHour(99);
time.setMinute(11);
time.setSecond(16.0);
System.out.println("现在时间是:"+time.getHour() + "/" +
time.getMinute() + ":" +
time.getSecond()
);
}

泛型的通配符

?: 表示可以使用任意的泛型类型对象、使其具备通用性
多态在泛型中不适用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void main(String[] args) {

ArrayList<String> list1 = new ArrayList<>();
list1.add("xiaobo");

ArrayList<Integer> list2 = new ArrayList<>();
list2.add(21);

getList(list1);
getList(list2);
}

public static void getList(ArrayList<?> arrayList){
System.out.println(arrayList);
}

泛型的上限和下限

上限

实例化具体的数据类型、可以是上限类型的子类或者是上限类型的本身、用extends表示、 类名<泛型标识 extends 上限类名>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class T<M> {

public static void main(String[] args) {

test(new T<Integer>());
test(new T<Float>());
test(new T<Double>());

}

public static void test(T<? extends Number> t){
System.out.println(t);
}
}

下限

实例化具体的数据类型、可以是下限类型的父类或者是下限类型的本身、用super表示 类名<泛型标识 super 下限类名>

1
2
3
4
5
6
7
8
9
10
11
12
public class T<M> {

public static void main(String[] args) {

test2(new T<Object>());

}

public static void test2(T<? super String> t){
System.out.println(t);
}
}

泛型接口

1
2
3
public interface MyInterface<T> {
public T getValue();
}

实现类在定义时继续使用泛型标识

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MyInterfaceImpl implements MyInterface<T>  {

private T obj;

public MyInterfaceImpl(T obj) {
this.obj = obj;
}

@Override
public T getValue() {
return this.obj;
}
}

实现类在定义时直接给出具体的数据类型

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MyInterfaceImpl2 implements MyInterface<String> {

private String obj;

public MyInterfaceImpl2(String obj) {
this.obj = obj;
}

@Override
public String getValue() {
return this.obj;
}
}

正确的开始、微小的长进、然后持续、嘿、我是小博、带你一起看我目之所及的世界……

-------------本文结束 感谢您的阅读-------------

本文标题:集合框架&泛型

文章作者:小博

发布时间:2021年06月12日 - 12:23

最后更新:2021年06月13日 - 01:00

原始链接:https://codexiaobo.github.io/posts/29725478/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。