[TOC]

Collection集合框架

描述: 集合的由来数组长度是固定,当添加的元素超过了数组的长度时需要对数组重新定义太麻烦,java内部给我们提供了集合类能存储任意对象,长度是可以改变的,随着元素的增加而增加,随着元素的减少而减少;

集合原理:(重点)

  • 集合的底层部分采用数组方式,比如创建一个10个大小的数组,之后往里面填数组当填满之后,它又创建了一个比原数组1.5倍大的数组,把原数组的数据都拷贝到新数组中,原数组将成为垃圾被丢弃;(然后一直循环)


数组和集合的区别

  • 区别1 :
    • 数组既可以存储基本数据类型,又可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值
    • 集合只能存储引用数据类型(对象)集合中也可以存储基本数据类型,但是在存储的时候会自动装箱变成对象
  • 区别2:
    • 数组长度是固定的,不能自动增长
    • 集合的长度的是可变的,可以根据元素的增加而增长


集合继承体系图:
Collection(单列集合的根接口)

  • List : 有序(存和取的顺序一致),有索引可以存储重复;
    • ArrayList 数组实现
    • LinkedList 链表实现
    • Vector (已被替换掉) 数组实现
  • Set : 无序()存和取的顺序补一致,无索引不可以存储重复;
    • HashSet 哈希算法
    • TreeSet 二叉数算法
WeiyiGeek.集合继承体系图

WeiyiGeek.集合继承体系图

数组和集合什么时候用?

  • 1.如果元素个数是固定的推荐用数组;
  • 2.如果元素个数不是固定的推荐用集合;

注意事项:

  • collectionXxx.java使用了未经检查或不安全的操作.
  • 要了解详细信息,请使用 -Xlint:unchecked重新编译.java编译器认为该程序存在安全隐患温馨提示:这不是编译失败,所以先不用理会,等学了泛型你就知道了

基础语法:

1
2
3
4
5
6
7
8
9
10
11
12
java.util 

public interface Collection<E> //<E> 泛型 jdk1.5出现所以,注意接口不能直接new需要找到它的已知实现类;
extends Iterable<E> //扩展迭代器

#实例化常常采用集合继承体系进行实现
boolean add(E e) //#确保此集合包含指定的元素(可选操作)。
boolean remove(Object o) //#从这个集合中移除指定元素的一个实例,如果它是存在的(可选操作)。
int size() //#返回此集合中的元素的数目。
boolean contains(Object o) //#返回 true如果集合包含指定元素。
boolean isEmpty() // #返回 true如果集合不包含任何元素。
void clear() //#从这个集合中移除所有的元素(可选操作)。


集合继承ArrayList

基础实例:
需求:我有5个学生,请把这个5个学生的信息存储到数组中,并遍历数组,获取得到每一个学生信息。

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
package com.weiyi.Collection;
//创建一个学生类
public class Students {
private String name;
private int age;
//创建空参和有参
public Students() {
}
public Students(String name, int age) {
this.name = name;
this.age = age;
}

//创建get/setter 方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}

案例需要上面的学生类
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
53
54
55
56
57
package com.weiyigeek.Collection;
import java.util.ArrayList;
import java.util.Collection;

import com.weiyi.Collection.Students; //引入学生类

public class Demo1_Collection {
/**
* Student[] arr = new Student[5]; //存储学生对象
arr[0] = new Student("张三", 23);
arr[1] = new Student("李四", 24);
arr[2] = new Student("王五", 25);
arr[3] = new Student("赵六", 26);
arr[4] = new Student("马哥", 20);
*
*/
public static void main(String[] args) {
//示例1.基本数据类型数组
//int[] arr = new int[5];

//示例2.引用数据类型数组
Students[] arrs = new Students[5];
arrs[0] = new Students("张三", 23);
arrs[1] = new Students("李四", 25);
arrs[2] = new Students("王五", 27);

for (int i = 0; i < arrs.length; i++) {
System.out.println(arrs[i]); //数组和集合引用数据类型存储都是地址值
}

//示例3.Collection类的使用 (编译看父类,运行看子类)
Collection c = new ArrayList(); //父类引用指向子类对象
//add方法如果是List集合一直都返回True,因为List集合中是可以存储重复元素的;但如果是set集合当存储重复元素的时候就会返回false;
boolean b1 = c.add("abc");
boolean b2 = c.add(true); //自动装箱特性new Boolean(true)
boolean b3 = c.add(100);
boolean b4 = c.add(10.24);
boolean b5 = c.add(new Students("张三",23));
boolean b6 = c.add("abc"); //可以添加重复的元素
System.out.println(c); //类似于Python中的集合
//ArrayList 的父类的父类重写toString方法,所以在打印对象的引用的时候输出的结果不是Object类中的toString方法
System.out.println(c.toString()); //类似于Python中的集合

//示例4.其他的方法
System.out.println("集合元素个数 :" + c.size());//获取集合中元素个数

c.remove("abc"); //删除元素
System.out.println("删除指定元素 : "+c); //类似于Python中的集合

System.out.println("判断是否包含 " + c.contains(10.24));

c.clear();//清空元素
System.out.println("清空元素 : " + c); //类似于Python中的集合

System.out.println("判断是否为空 : " + c.isEmpty()); //判断集合是否为空
}
}

执行结果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[email protected]15db9742
[email protected]6d06d69c
[email protected]7852e922
null
null

[abc, true, 100, 10.24, [email protected]4e25154f, abc]
[abc, true, 100, 10.24, [email protected]4e25154f, abc]

集合元素个数 :6
删除指定元素 : [true, 100, 10.24, [email protected]4e25154f, abc]
判断是否包含 true
清空元素 : []
判断是否为空 : true

Tips : 数组和集合存储引用数据类型存的都是地址值
WeiyiGeek.

WeiyiGeek.


集合转数组遍历:
描述:集合常用方法

1
2
3
4
5
Object[] toArray()  //#返回包含此集合中所有元素的数组。 
boolean addAll(Collection c) //#将指定集合中的所有元素添加到这个集合(可选操作)。
boolean removeAll(Collection c) //#删除此集合中包含的所有元素(可选操作)的所有元素(可选操作)。
boolean containsAll(Collection c) //#返回 true如果这个集合包含指定集合的所有元素。
boolean retainAll(Collection c) //#仅保留包含在指定集合中的这个集合中的元素(可选操作)。 交集

基础示例:

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package com.weiyigeek.Collection;
import java.util.ArrayList;
import java.util.Collection;

import com.weiyi.Collection.Students;

public class Demo2_Collection {

public static void main(String[] args) {
//示例1:集合遍历之集合转数组遍历
Collection c = new ArrayList();
c.add("a");
c.add("b");
c.add("c");
c.add("d");
Object[] arr = c.toArray(); //集合之数组遍历
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}


System.out.println("\n##########分割线上##########");
//示例2.集合转换成为数组
Collection c1 = new ArrayList();
c1.add(new Students("赵老师",24));
c1.add(new Students("经老师",23));
c1.add(new Students("渣渣辉",25));
c1.add(new Students("刘师傅",26));
Object[] arr1 = c1.toArray(); //将集合转换成数组
for (int i = 0; i < arr1.length; i++) {
Students s = (Students)arr1[i]; //向下转型
System.out.println(s.getName() + " " + s.getAge()); //重点值得学习
}


//示例3.自带All()功能测试方法
Collection c2 = new ArrayList();
c2.add("a");
c2.add("b");
c2.add("c");
c2.add("d");

Collection c3 = new ArrayList();
c3.add("1");
c3.add("2");
c3.add("3");
c3.add("4");
c3.add("a");

System.out.println("##########分割线###########");
c2.add(c3); //将c3看成一个对象添加到c1中 [1,2,3,4]
System.out.println(c2);
c2.addAll(c3); //将c3中的每一个元素添加到c1中
System.out.println(c2);

boolean b = c2.removeAll(c3); //将c2中的c3元素进行删除 (需要注意删除是交集)
System.out.println("需要注意删除是交集");
System.out.println(c2);

boolean b1 = c2.containsAll(c3); //判断调用集合是否包含传入的集合
System.out.println("c2是否包含c3 : " + b1);

//取交集如果调用的集合改变就返回true(持续),否则返回false;
boolean b2 = c2.retainAll(c3); //取交集
System.out.println(b2);
System.out.println(c2);
}
}

执行结果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
a b c d 
##########分割线上##########
赵老师 24
经老师 23
渣渣辉 25
刘师傅 26
##########分割线###########
[a, b, c, d, [1, 2, 3, 4]]
[a, b, c, d, [1, 2, 3, 4], 1, 2, 3, 4]
需要注意删除是交集
[a, b, c, d, [1, 2, 3, 4]]
c2是否包含c3 : false
true
[]


集合之迭代器(Iterator)

描述:其实迭代都是遍历,而遍历也可以看做是迭代;迭代器概述集合是用来存储元素,存储的元素需要查看,那么就需要迭代(遍历);

迭代器原理:

  • 迭代器是对集合进行遍历,而每一个集合内部的存储结构都是不同的,所以每一个集合存和取都是不一样,那么就需要在每一个类中定义hasNext()和next()方法
  • 这样做是可以的,但是会让整个集合体系过于臃肿,迭代器是将这样的方法向上抽取出接口,然后在每个类的内部,定义自己迭代方式好处有二:
    • 第一规定了整个集合体系的遍历方式都是hasNext()和next()方法
    • 第二代码有底层内部实现,使用者不用管怎么实现的会用即可
1
2
3
4
5
#迭代器方法解析
java.util
public interface Iterator<E> #返回此集合中的元素的迭代器。
boolean hasNext() #返回 true如果迭代具有更多的元素。
E next() #返回迭代中的下一个元素。

迭代器源码解析

1
2
3
4
5
6
* 1,在eclipse中ctrl + shift + t找到ArrayList类
* 2,ctrl+o查找iterator()方法
* 3,查看返回值类型是new Itr(),说明Itr这个类实现Iterator接口
* 4,查找Itr这个内部类,发现重写了Iterator中的所有抽象方法
* 5,hasNext() 是判断集合中是否有参数,以及cursor标志位是否 == 集合的size个数
* 6,Next() 是集合进行迭代并输出迭代值

基础方法:

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
package com.weiyigeek.Collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import com.weiyi.Collection.Students;

@SuppressWarnings("rawtypes")

public class Demo3_Collection {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
//示例1.对集合中的元素进行迭代遍历
Collection c = new ArrayList();
c.add("Weiyi");
c.add("Geek");
c.add("1024");
c.add("Java");
Iterator it = c.iterator(); //获取迭代器
boolean bl = it.hasNext(); //判断集合中是否有元素,有则返回true;
Object obj = it.next(); //指针会记录当前位置向后移位;
System.out.print(bl + " ");
System.out.println(obj); //输入集合中第一个元素
while(it.hasNext())
{
System.out.println(it.next());
}


//示例2.通过while循环来迭代集合数组
Collection c1 = new ArrayList();
c1.add(new Students("张伟", 15)); //父类引用指向子类对象
c1.add(new Students("张杰", 29)); //Object obj = new Student
c1.add(new Students("张根硕", 35));
c1.add(new Students("大张伟", 25));
Iterator it1 = c1.iterator();
//Collection存储自定义对象并用迭代器遍历
while(it1.hasNext())
{
Students s = (Students)it1.next(); //向下转型 强转
System.out.println(s.getName() + " " + s.getAge());
}
}
}

执行结果:
1
2
3
4
5
6
7
8
9
true Weiyi
Geek
1024
Java

张伟 15
张杰 29
张根硕 35
大张伟 25


有序集合List

描述:List集合中不能有重复元素,否则返回false;List集合中才有索引,而set中是没有索引的
List集合的特有功能

1
2
3
4
* void add(int index,E element)
* E remove(int index)
* E get(int index)
* E set(int index,E element)

基础示例:

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
package com.weiyigeek.Collection;

import java.util.List;
import java.util.ArrayList;
import com.weiyi.Collection.Students;

public class Demo4_List {

public static void main(String[] args) {
//1.List集合功能(按照索引插入)
List l = new ArrayList(); //注意是在java.util.List;
l.add("Weiyi"); //object obj = new String();
l.add("Geek");
l.add("Love");
l.add("Java");
l.add(0,"Start"); //头部插入 INDEX <= SIZE 并且 Index >= 0 不会报索引异常
l.add(5,"END"); //尾部插入
System.out.println(l);

//示例2.通过索引删除元素并且其返回
Object demo1 = l.remove(3); //删除Love - 注意:删除的时候不会自动装箱
System.out.println(l + " 删除的集合元素是 " + demo1);

//示例3.根据索引获取元素
Object demo2 = l.get(1);
System.out.println("获取指定的索引的集合元素 :" + demo2 + l.get(2));
//通过索引遍历List集合;
for (int i = 0; i < l.size(); i++) {
System.out.print(l.get(i) + " - ");
}

//示例4.根据索引进行指定位置元素进行修改
l.set(3, "Editer");
System.out.println("\n修改后的集合元素 : " + l);

//综合实例
//向List集合中存储学生对象然后通过size和get()方法结合遍历
List list = new ArrayList();
list.add(new Students("Weiyi",28));
list.add(new Students("Geek",32));

for (int i = 0; i < list.size(); i++) {
//存储自定义对象通过size()和get()方式获取
Students s = (Students)list.get(i); //向下引用
System.out.println(i + " - " + s.getName() + " " + s.getAge());
}
}
}

执行结果:
1
2
3
4
5
6
7
[Start, Weiyi, Geek, Love, Java, END]
[Start, Weiyi, Geek, Java, END] 删除的集合元素是 Love
获取指定的索引的集合元素 :WeiyiGeek
Start - Weiyi - Geek - Java - END -
修改后的集合元素 : [Start, Weiyi, Geek, Editer, END]
0 - Weiyi 28
1 - Geek 32


集合继承Vector

描述:Vector是Java中的老员工了从jdk1.0但是现在已经被ArrayList所替代,Vector类实现了一个可增长对象数组,可以通过索引来访问元素,也可以根据需求来进行收缩对象数组;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#包
java.util.Vector<E>

#类
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable


#成员属性
protected int elementCount //#Vector对象的有效成分的数量。成分 elementData[0]通过 elementData[elementCount-1]是实际的项目

//#Vector类特有功能
* public void addElement(E obj) //添加元素
* public E elementAt(int index)
* public Enumeration elements()

//#迭代方式
public interface Enumeration<E> //一个实现枚举接口的对象生成一系列元素,一个在一个时间。连续调用方法返回的 nextElement连续单元系列。
boolean hasMoreElements() //#测试此枚举是否包含更多元素。
E nextElement() //#返回此枚举的下一个元素,如果此枚举对象至少有一个元素可以提供。

基础示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//示例1.Vector的迭代与添加元素
Vector v = new Vector();
v.addElement("Weiyi");
v.addElement("Geek");
v.addElement("Java");
Enumeration en = v.elements(); //获取枚举
while(en.hasMoreElements()) //判断集合中是否有元素
{
//迭代获取集合中的元素
System.out.print(en.nextElement() + " ");
}

//执行结果
Weiyi
Geek
Java


集合继承LinkedList

描述:双向链表实现的 List和 Deque接口。实现了所有的可选列表操作,并允许所有元素(包括 null)。
可以实现栈(先进后出)和堆(先进先出)的数据结构;
基础语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#包
java.util

#类结构
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, Serializable

#构造方法
LinkedList() #构造一个空列表。
LinkedList(Collection<? extends E> c) #构造一个包含指定集合的元素的列表,它们在集合的迭代器返回的顺序中返回。

#常用方法
* public void addFirst(E e)及addLast(E e)
* public E getFirst() 及 getLast()
* public E removeFirst() 及 public E removeLast()
* public E get(int index);

基础示例:

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
package com.weiyigeek.Collection;
import java.util.LinkedList;
public class Demo8_linkedList {
public static void main(String[] args) {
//示例1.集合常用方法展示
LinkedList list = new LinkedList(); //创建Linked对象
list.add("1");
list.addFirst("0");
list.addLast("2");

System.out.println("获取集合中第一个元素:"+list.getFirst());
System.out.println("获取集合中最后一个元素:"+list.getLast());
System.out.println("返回删除的第一个元素:"+list.removeFirst());
System.out.println("返回删除的最后一个元素:"+list.removeLast());
System.out.println("利用索引获取元素 (原理值得学习): "+list.get(0));

//示例2.采用LinkedList模拟栈结构
LinkedStack stack = new LinkedStack();
stack.in("a"); //进栈
stack.in("b");
stack.in("c");
stack.in("d");
//循环弹栈
while(!stack.isEmpty()) {
System.out.println(stack.out());
}

//示例3.实现堆即先进先出采用addFrist();以及RemoveFrist()即可
}
}

//封装成为类
class LinkedStack {
private LinkedList lt = new LinkedList();

/**模拟栈先进先出**/
public void in(Object obj) {
lt.addLast(obj); //向末尾添加方法
}
public Object out() {
return lt.removeLast(); //向末尾删除方法
}

//判断是否为空
public boolean isEmpty() {
return lt.isEmpty();
}
}

执行结果:
1
2
3
4
5
6
7
8
9
10
获取集合中第一个元素:0
获取集合中最后一个元素:2
返回删除的第一个元素:0
返回删除的最后一个元素:2
利用索引获取元素 (原理值得学习): 1

d
c
b
a


List子类特点

描述:在说List子类特点的时候我们先说说数据结构之数组和链表_
数组与链表的区别?
A:数组:查询快修改也快,但是增删慢;
B:链表:查询慢修改也慢,但是增删快;

List的三个子类的特点?

  • ArrayList:
    • 底层数据结构是数组,查询快,增删慢。
    • 线程不安全,效率高
  • Vector:
    • 底层数据结构是数组,查询快,增删慢。
    • 线程安全,效率低
    • Vector相对ArrayList查询慢(线程安全的)
    • Vector相对LinkedList增删慢(数组结构)
  • LinkedList:
    • 底层数据结构是链表,查询慢,增删快。
    • 线程不安全,效率高

Vector和ArrayList的区别

  • Vector是线程安全的,效率低
  • ArrayList是线程不安全的,效率高
    共同点:都是数组实现的

ArrayList和LinkedList的区别

  • ArrayList底层是数组结果,查询和修改快
  • LinkedList底层是链表结构的,增和删比较快,查询和修改比较慢
    共同点:都是线程不安全的
  • List有三个儿子,我们到底使用谁呢?
    查询多用ArrayList
    增删多用LinkedList
    如果都多ArrayList


ArrayList示例

描述:前面我们已经简单的介绍了一些ArrayList集合的框架,下面直接演示集合参数过滤
基础示例:

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package com.weiyigeek.Collection;

import java.util.ArrayList;
import java.util.Iterator;
import com.weiyi.Collection.Students; //重写了toString和equals方法

public class Demo7_ArrayList {
public static void main(String[] args)
{
/**
* A:案例演示
* 需求:ArrayList去除集合中字符串的重复值(字符串的内容相同)
* 思路:创建新集合方式
*/
ArrayList newList = new ArrayList();
newList.add("a");
newList.add("c");
newList.add("b");
newList.add("b");
newList.add("b");

ArrayList list = getSingle(newList);
System.out.println(list);

/**
B:案例演示
* 需求:ArrayList去除集合中自定义对象元素的重复值(对象的成员变量值相同)
* **/
ArrayList objList = new ArrayList();
objList.add(new Students("张三",13)); //如果采用Object方式是对比的地址值是不一样的
objList.add(new Students("张三",13));
objList.add(new Students("张四",13));
objList.add(new Students("王三",13));
ArrayList objres = getSingleObj(objList); //循环方法进行对象去重
objList.remove(new Students("张三",13)); //底层都是依赖于object的equals方法
System.out.println(objres);
}

/*
* 参数: 去除重复
* 1,返回ArrayList类型类别
* 2,参数列表ArrayList
* 创建新集合、根据传入的集合获取迭代器
* 遍历老集合、通过新集合判断是否包含老集合中的元素,如果不包含就不添加;
*/
public static ArrayList getSingle(ArrayList list) {
ArrayList newList = new ArrayList(); //创建一个新集合
Iterator it = list.iterator(); //获取迭代器
while(it.hasNext()) { //判断老集合中是否有元素
String temp = (String)it.next(); //将每一个元素临时记录住
if(!newList.contains(temp)) { //如果新集合中不包含该元素
newList.add(temp); //将该元素添加到新集合中
}
}
return newList; //将新集合返回
}

//可以处理比较对象的类
private static ArrayList getSingleObj(ArrayList objList) {
ArrayList newList = new ArrayList();
Iterator it = objList.iterator();
while(it.hasNext())
{
Object obj = it.next();
if(!newList.contains(obj))
{
newList.add(obj);
}
}
return newList;
}
}


集合泛型

泛型概述:比如Collection集合上有一个尖括号<引用数据类型>,一旦设置引用数类型限定您集合存储的数据类型,只能使用引用对象及该对象的子类对象(父类可以指向子类对象);

泛型好处:

  • 提高安全性(将运行期的错误转换到编译期)
  • 省去强转的麻烦

泛型基本使用:

  • <>中放的必须是引用数据类型,从而限定集合中使用的数据类型;

泛型使用注意事项:

1
2
3
4
5
#前后的泛型必须一致
ArrayList<Students> lt = new ArrayList<Students>()

#或者后面的泛型可以省略不写(1.7的新特性菱形泛型)
ArrayList<Students> lt = new ArrayList<>()

基础示例:

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package com.weiyi.generic;
import java.util.ArrayList;
import java.util.Iterator;

//引用我们students类
import com.weiyi.Collection.Students;
public class Demo1_Generic {
public static void main(String[] args) {
//示例0.泛型的使用(字符串类型)
ArrayList<String> list = new ArrayList<>(); //泛型可以省略不写(1.7的新特性菱形泛型)
list.add("a");
list.add("b");
list.add("c");
Iterator<String> llt = list.iterator();
while(llt.hasNext()) {
System.out.println(llt.next());
}

//示例1.ArrayList存储字符串并遍历泛型版
ArrayList<Students> lt = new ArrayList<Students>();//关键点1 数据引用类型一定要相同,后面也可以是前引用类型的子类或者父类
lt.add(new Students("渣渣辉",25));
lt.add(new Students("掌门人",22));
lt.add(new Students("柳师傅",21));

Iterator<Students> ltr = lt.iterator(); //关键点2(注意泛型集合是什么类型,迭代器便是什么类型)
while(ltr.hasNext())
{
Students obj = ltr.next(); //这里不用强转
System.out.println(obj.getName() +" ---- "+ obj.getAge()); //注意这里如果调用一次.next()指向的就是下一个对象
}
/***
* 执行结果:
* 渣渣辉 ---- 25
* 掌门人 ---- 22
* 柳师傅 ---- 21
**/

//示例2.泛型的由来:通过Object转型问题引入
/* 早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的问题。
* 也就存在这隐患,所以Java提供了泛型来解决这个安全问题。
**/
Tool t = new Tool(); //创建工具类对象
t.setObj(new Person("张三",24)); //父类指向子类对象

Worker w = (Worker) t.getObj(); //向下转型
System.out.println(w); //会出现ClassCastException
//其实泛型就像是种瓜得瓜种豆得豆一样
/***执行结果
* Exception in thread "main" java.lang.ClassCastException: com.weiyi.generic.Person cannot be cast to com.weiyi.generic.Worker
at com.weiyi.generic.Demo1_Generic.main(Demo1_Generic.java:47)
*/
}
}

//示例2演示
class Tool{
private Object obj;
//alt + shift + s + r
public Object getObj() {return obj;}
public void setObj(Object obj) {
this.obj = obj; //父类引用子类对象
}
}

//继承类
class Person extends Students {
public Person() {super();}
public Person(String name, int age) {super(name, age);}
}

class Worker extends Students {
public Worker() {super();}
public Worker(String name, int age) {super(name, age);}
}


泛型类/方法/接口的概述及使用

泛型类概述: 把泛型定义在类上
定义格式: public class 类名<泛型类型1,…>

泛型方法概述: 把泛型定义在方法上,如果是静态方法需要在static后加入自己的泛型;
定义格式: public <泛型类型> 返回类型 方法名(泛型类型 变量名)

泛型接口概述: 把泛型定义在接口上
定义格式: public interface 接口名<泛型类型>

基础案例:

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
53
54
package com.weiyi.generic;
public class Demo2_Generic {
public static void main(String[] args) {
//示例1.泛型类的使用
Tools<String> tls = new Tools<>();
tls.show("Hello World!");
tls.showMethod("Yes");
tls.showStatic("Generic");

//示例2.接口泛型
Demo d1 = new Demo();
d1.show("Interfaces");

Demo1<String> d2 = new Demo1();
d2.show("Interfaces");
}
}

//示例1.泛型类(一个字符大写 常用E)
class Tools<Q> {
private Q obj; //泛型传入是什么类型就是什么类型
public Q getObj() {return obj;}
public void setObj(Q obj) {this.obj = obj;}
public void show(Q str) {
System.out.println("类泛型:"+str);
}
//示例2.方法泛型最好与类的泛型是一致,如果不一致需要在方法上声明该泛型
public<T> void showMethod(T t) {
System.out.println("方法泛型:"+t);
}
//示例3.注意:类中静态方法随着类的加载而加载,在加载的时候可能还没出现对象;所以说在静态方法泛型上也必须声明自己的泛型
public static<W> void showStatic(W w) {
System.out.println("静态方法泛型:"+w);
}
}
//示例2.泛型接口(一个字符大写 常用E)
interface Inter<T> {
public void show(T t);
}
//方式1:推荐方式
class Demo implements Inter<String> {
@Override
public void show(String t) {
System.out.println("泛型接口-示例1:"+t);
}
}
//方式2:没有必要在使用接口的时候指定泛型
class Demo1<T> implements Inter<T>
{
@Override
public void show(T t) {
System.out.println("泛型接口-示例2:"+t);
}
}

执行结果:
1
2
3
4
5
类泛型:Hello World!
方法泛型:Yes
静态方法泛型:Generic
泛型接口-示例1:Interfaces
泛型接口-示例2:Interfaces

注意事项: 泛型类型必须是引用类型;


泛型高级之通配符

描述:泛型通配符<?>, 任意类型如果引用类型没有明确,那么就是Object以及任意的Java类了;

1
2
? extends E  向下限定,E及其子类
? super E 向上限定,E及其父类

基础实例:
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
package com.weiyi.generic;
import com.weiyi.Collection.Students;
import java.util.ArrayList;
import java.util.List;
public class Demo3_Generic {
public static void main(String[] args) {
//实例1.当右边的泛型不确定时,左边可以指定为?
List<?> list = new ArrayList<Integer>();

//实例2.通配符案例验证
ArrayList<Study> list1 = new ArrayList<>();
list1.add(new Study("1.王老五", 15)); //子类
list1.add(new Study("2.王老吉", 15));
list1.add(new Study("3.王老四", 15));

ArrayList<Students> list2 = new ArrayList<>();
list2.add(new Students("4.测试",25)); //父类
list2.add(new Students("5.学生类",25));

list2.addAll(list1); //父类添加拼接子类的集合 (注意不能父类强制转换成为子类list1.addAll(list2))
System.out.println("输出结果:"+list2);
}
}

//实例1
class Study extends Students {
public Study() {
super();
}
public Study(String name, int age) {
super(name, age);
}
}

执行结果:
1
输出结果:[Students [name=4.测试, age=25], Students [name=5.学生类, age=25], Students [name=1.王老五, age=15], Students [name=2.王老吉, age=15], Students [name=3.王老四, age=15]]


集合框架进阶

1.增强for的概述和使用
概述:简化数组和Collection集合的遍历,增强for循环底层由迭代器实现;

1
2
3
for(元素数据类型 变量 : 数组或者Collection集合) {
使用变量即可,该变量就是元素
}

基础实例:
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
//#实例
package com.weiyi.generic;
import java.util.ArrayList;
import com.weiyi.Collection.Students;
public class Demo4_For {

public static void main(String[] args) {
//实例1.增强for遍历数组
int[] arr = {11,22,33,44,55};
//foreach 迭代(值得学习)
for (int i : arr) {
System.out.print(i+" ");
}
System.out.println();


//实例2.增强for遍历集合存储元素
ArrayList<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
for (String param : list) {
System.out.print(param+" ");
}
System.out.println();


//实例3.ArrayList存储字符串和自定义对象并遍历增强for版
ArrayList<Students> list1 = new ArrayList<Students>();
list1.add(new Students("渣渣哥", 27));
list1.add(new Students("刘师傅", 26));
list1.add(new Students("帐老师", 27));

for (Students param : list1) {
System.out.println(param); //这里是由于重写了toString的效果
}
}
}

//#执行结果:
11 22 33 44 55
a b c d
Students [name=渣渣哥, age=27]
Students [name=刘师傅, age=26]
Students [name=帐老师, age=27]


2.三种迭代的能否删除

  • 普通for循环,可以删除,但是索引要– (自减)
  • 迭代器,可以删除,但是必须使用迭代器自身的remove方法,否则会出现并发修改异常
  • 增强for循环不能删除
    基础实例:
    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
    package com.weiyi.generic;
    import java.util.ArrayList;
    import java.util.Iterator;
    import com.weiyi.Collection.Students;
    public class Demo5_RemoveCollection {
    public static void main(String[] args) {
    //实例1.三种迭代方法是否能进行删除
    ArrayList<String> list = new ArrayList<String>();
    list.add("a");
    list.add("a");
    list.add("b");
    list.add("c");
    list.add("WeiyiGeek");


    //(1)如果要删除的元素是挨着的,普通循环只能对其index索引减减<-重点
    for (int i = 0; i < list.size(); i++) {
    if("a".equals(list.get(i)))
    list.remove(i--); //注意这里是先赋值,再减减
    }

    //(2)迭代器删除
    Iterator<String> it = list.iterator();
    while(it.hasNext())
    {
    if("b".equals(it.next()))
    //注意这里不能使用集合的删除方法会导致并发修改异常(迭代过程中进行了修改),因为迭代过程中如果集合被修改,便会导致迭代修改异常
    it.remove();
    }

    //宁一种方式 与上面的区别就是 不能重复使用迭代器it1
    for(Iterator<String> it1 = list.iterator(); it.hasNext();)
    {
    if("c".equals(it1.next()))
    it1.remove();
    }


    //(3)增强for循环不能删除只可以遍历
    for(String param: list){
    if("c".equals(param))
    //list.remove(param);
    System.out.println(param);

    System.out.println("外层 : " + param);
    }
    System.out.println(list);
    }
    }
    执行结果:
    1
    2
    3
    4
    c
    外层 : c
    外层 : WeiyiGeek
    [c, WeiyiGeek]


3.集合嵌套之ArrayList嵌套ArrayList
基础示例:

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
import java.util.ArrayList;

import com.weiyi.Collection.Students;

public class Demo3_ArrayLists {

public static void main(String[] args) {
//示例:集合嵌套ArrayList中的ArrayList
ArrayList<ArrayList<Students>> list = new ArrayList<ArrayList<Students>>(); //当做一个年级
ArrayList<Students> first = new ArrayList<Students>(); //第一个班级
first.add(new Students("张伟",25));
first.add(new Students("大张伟",25));
first.add(new Students("纳音",25));

ArrayList<Students> seconde = new ArrayList<Students>(); //第二个班级
seconde.add(new Students("Love", 99));
seconde.add(new Students("Test", 199));

//将班级加到年级集合中
list.add(first);
list.add(seconde);

//遍历学科集合(值得学习)
for (ArrayList<Students> x: list) {
for (Students y : x) {
System.out.println(y);
}
}
}
}
#执行结果
Students [name=张伟, age=25]
Students [name=大张伟, age=25]
Students [name=纳音, age=25]
Students [name=Love, age=99]
Students [name=Test, age=199]


集合异常

问题1:集合框架(并发修改异常产生的原因及解决方案)
ListIterator常用方法:

1
2
3
4
* boolean hasNext()是否有下一个
* boolean hasPrevious()是否有前一个
* Object next()返回下一个元素
* Object previous();返回上一个元素

案例演示需求:我有一个集合,请问,我想判断里面有没有”world”这个元素,如果有,我就添加一个”javaee”元素,请写代码实现。

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
53
54
package com.weiyigeek.Collection;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class Demo5_ListIterator {

public static void main(String[] args) {
//方式1:
List list = new ArrayList();
list.add("Weiyi");
list.add("world");
list.add("Geek");

//采用:常规Iterator迭代器
Iterator it = list.iterator();
boolean flag = false;
while(it.hasNext())
{
String str = (String)it.next();
if(str.equals("world")) {
//list.add("JavaEE") //这里会抛出ConcurrentModificationException并发修改异常
//迭代器遍历集合修改集合,异常由于迭代器已经知道集合的个数,然而在迭代的时候又添加了集合元素所以导致异常
//所以采用此种方法
flag = true;
break;
}
}
if(flag) {
list.add("JavaEE");
}
System.out.println("方法1:" + list);


//方式2:
//* a:迭代器迭代元素,迭代器修改元素(ListIterator的特有功能add)
//* b:集合遍历元素,集合修改元素
ListIterator lit = list.listIterator(); //如果想在遍历的过程中添加元素,可以用ListIterator中的add方法
while(lit.hasNext()) {
String str = (String)lit.next();
if(str.equals("world")) {
//它会立即在找到world后面进行添加javaee
lit.add("javaee"); //关键点 lit的 ListIterator在迭代的过程中添加元素对象;
}
}
System.out.println("方式2:"+list);
}
}

//###########执行结果##############
方法1:[Weiyi, world, Geek, JavaEE]
方式2:[Weiyi, world, javaee, Geek, JavaEE]