黑马程序员——Java基础---集合类(上)

时间:2023-02-15 10:06:30

------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------

集合类知识目录:

一、集合概述

1、对象数组的概述和使用
2、对象数组的内存(图解)
3、集合的由来及集合的继承体系图

二、conllection接口
1、Collection接口概述
2、Collection中的基本方法
3、Collection中批量操作元素的方法
4、Collection中遍历
5、Collection存储自定义对象并遍历
6、迭代器的原理及源码解析
三、List接口
1、List概述
2、List的特点
3、小结_Collection接口和List接口
4、并发修改异常
5、使用List存储自定义对象并遍历
6、自定义集合类_数组实现
7、自定义集合类_链表实现
8、常见数据结构(图解)
四、List的三个子类知识详解
1、List接口的三个子类
2、ArrayList存储自定义对象并遍历
3、Vector存储自定义对象并遍历
4、LinkedList集合
5、去除ArrayList中重复的元素(练习)
6、用LinkedList模拟栈数据结构的集合并测试(练习)
五、JDK1.5新特性——泛型
1、泛型概述
2、泛型类
3、泛型方法
4、泛型接口
5、泛型通配符
六、JDK5.0新特性——foreach循环
1、增强for循环(forEach循环)概述
2、ArrayList存储自定义对象并遍历增强for版(练习)
七、静态导入的概述和使用
八、可变参数
九、Arrays类
十、集合嵌套之ArrayList嵌套ArrayList

总结

集合类知识详解:

一、集合概述

1、对象数组的概述和使用

 * Student[] stuArray = new Student[120];
 * 1.定义了一个120个长度的Student数组;
 * 2.数组的每个元素存储的是一个:Student对象的引用;
 * 3.此时,没有任何的Student对象产生;
 * 4.由于数组是引用类型的数组,所以每个元素都被初始化为:null 
 * 对象数组的弊端:
 * 1.一旦确定长度后,其长度就不能再更改了;这对我们程序员使用起来非常的不方便;
 * 2.数组定义时需要指定数据类型,那么就只能存储这个类型的数据;
 * 针对数组的弊端:Java为我们程序员提供了一种新的工具:集合
 * 1.集合的作用:就是用来装"对象的引用";
 * 2.这些集合就类似于"仓库",我们程序员使用起来, 就可以将它看做是一个:可以存储无限数量的引用的一个大仓库,我们程序员使用时,只需要往里面增、删、改、查元素,其它的操作我们不需要管。

class Student{
String name;
int age;
char sex;
int score;
}
public class Demo {
public static void main(String[] args) {
/*Student stu1 = new Student();
Student stu2 = new Student();
Student stu120 = new Student();*/
//定义一个3长度的Student数组:
Student[] stuArray = new Student[3];
Student stu1 = new Student();
stu1.name = "刘德华";
stu1.age = 20;
stu1.sex = '男';
stu1.score = 88;
Student stu2 = new Student();
stu2.name = "张学友";
stu2.age = 22;
stu2.sex = '男';
stu2.score = 99;
Student stu3 = new Student();
stu3.name = "章子怡";
stu3.age = 24;
stu3.sex = '女';
stu3.score = 100;
stuArray[0] = stu1;
stuArray[1] = stu2;
stuArray[2] = stu3;
//想新增一个对象,但数组已满,无法存更多的了。
Student stu4 = new Student();
stu4.name = "郭富城";
stu4.age = 26;
stu4.sex = '男';
stu4.score = 98;
int sum = 0;
for(int i = 0;i < stuArray.length ; i++){
Student stu = stuArray[i];
sum += stu.score;
}
System.out.println("总分:" + sum);
System.out.println("平均分:" + (sum / stuArray.length));
}
}
黑马程序员——Java基础---集合类(上)

2、对象数组的内存(图解)

黑马程序员——Java基础---集合类(上)

3、集合的由来及集合的继承体系图

 * 为什么出现集合类?
 * 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,Java就提供了集合类。
 * 数组和集合类同是容器,有何不同?
 * 数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象。
 * 集合类的特点?
 * 集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。

  1. 黑马程序员——Java基础---集合类(上)
  2. 黑马程序员——Java基础---集合类(上)

二、conllection接口

1、Collection接口概述

 * Collection 层次结构中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。
 * 一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。

2、Collection中的基本方法

 * 注意:如果大家在方法的形参或返回值类型中看到E字母,可以把它当做:Object
 * boolean add(Object e):将参数e添加到集合
 * boolean remove(Object o):将参数o从集合中移除
 * void clear():清空集合
 * boolean contains(Object o):基于equals()进行判断;
 * boolean isEmpty():判断集合是否为空
 * int size():集合中元素的数量;
 * 学习:Collection(List和Set的顶层接口)
 * 使用:子类:ArrayList

public class Demo {
public static void main(String[] args) {
//1.定义集合对象
Collection col = new ArrayList();//多态:可存储重复元素
Collection col2 = new HashSet();//不能存储重复元素;
//2.向仓库中添加元素
System.out.println(col.add("孙悟空"));
System.out.println(col.add("猪八戒"));
System.out.println(col.add("沙师弟"));
System.out.println(col.add("唐僧"));
System.out.println(col.add("唐僧"));
System.out.println("---------------------------");
System.out.println(col2.add("孙悟空"));
System.out.println(col2.add("猪八戒"));
System.out.println(col2.add("孙悟空"));
System.out.println("集合元素:" + col);
//3.移除元素
System.out.println("删除元素:唐僧: " + col.remove("唐僧"));
System.out.println("删除元素:白骨精:" + col.remove("白骨精"));
System.out.println("集合元素:" + col);
//4.void clear()
//col.clear();
//System.out.println("清空集合后:" + col);
//5.boolean contains(Object o)
System.out.println("是否包含:白骨精:" + col.contains("白骨精"));
System.out.println("是否包含:孙悟空:" + col.contains("孙悟空"));
//6.boolean isEmpty()
//col.clear();
System.out.println("集合是否为空:" + col.isEmpty());
//7.int size():
System.out.println("集合中元素的数量:" + col.size());
//存储Student对象,使用数据,一旦定义长度,之后就不能改变;
//所以,如果我们使用"集合"存储,我们就不用关心长度的问题;

}
}
黑马程序员——Java基础---集合类(上)

3、Collection中批量操作元素的方法

 * boolean addAll(Collection c):将参数集合,一次性全部添加到当前集合
 * boolean removeAll(Collection c):移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作
 * boolean containsAll(Collection c):如果此 collection 包含指定 collection 中的所有元素,则返回 true
 * boolean retainAll(Collection c):移除此 collection 中未包含在指定 collection 中的所有元素。 

public class Demo {
public static void main(String[] args) {
Collection c1 = new ArrayList();
c1.add("孙悟空");
c1.add("猪八戒");
c1.add("唐三藏");
Collection c2 = new ArrayList();
c2.add("白骨精");
c2.add("蜘蛛精");
c2.add("狐狸精");
//将集合c2中的所有元素,一次性全部添加到c1中
/*c1.addAll(c2);
System.out.println("c1.size : " + c1.size());//6
System.out.println("c2.size : " + c2.size());//3
System.out.println("c1 : " + c1);
System.out.println("c2 : " + c2);
*/

/*c1.removeAll(c2);
System.out.println("c1 : " + c1);
System.out.println("c2 : " + c2);*/

//System.out.println(c1.containsAll(c2));
System.out.println(c1.retainAll(c2));
System.out.println("c1 : " + c1);
System.out.println("c2 : " + c2);
}
}
黑马程序员——Java基础---集合类(上)

4、Collection中遍历

 * 对于Collection类型的集合,有两种基本的遍历方法:
 * 1.Object[] toArray()方法:
 * 2.迭代器:Iterator iterator();
 *  Iterator(接口):
 *  boolean hasNext():  如果仍有元素可以迭代,则返回 true。 
 *  Object next() :返回迭代的下一个元素。 

public class Demo {
public static void main(String[] args) {
Collection c1 = new ArrayList();
c1.add("孙悟空");
c1.add("猪八戒");
c1.add("唐三藏");
//遍历方式一:
Object[] objArray = c1.toArray();
for(int i = 0;i < objArray.length ; i++){
System.out.println(objArray[i]);
}
System.out.println("---------------------------");
//遍历方式二:迭代器
Iterator it = c1.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
黑马程序员——Java基础---集合类(上)

5、Collection存储自定义对象并遍历

public class Student {
String name;
int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String toString(){
return "Student [姓名:" + name + ", 年龄:" + age + "]";
}
}
public class Demo {
public static void main(String[] args) {
//1.定义一个集合
Collection col = new ArrayList();
//2.存储对象
col.add(new Student("张三",20));
col.add(new Student("李四",22));
col.add(new Student("王五",24));
col.add(new Student("周六",26));
col.add(new Student("赵七",27));
//3.遍历
//遍历方式一:toArray()
Object[] objArray = col.toArray();
for(int i = 0 ;i < objArray.length ; i++){
System.out.println(objArray[i]);
}
System.out.println("-------迭代器----------------");
//遍历方式二:迭代器
Iterator it = col.iterator();
while(it.hasNext()){
//Object obj = it.next();
System.out.println(it.next());
}
}
}
黑马程序员——Java基础---集合类(上)

6、迭代器的原理及源码解析

interface Iterator{
boolean hasNext();
Object next();
void remove();
}
interface Collection{
Iterator iterator();
}
class ArrayList implements Collection{
public Iterator iterator() {
return new Itr();
}
private class Itr implements Iterator{
public boolean hasNext() {
return false;
}
public Object next() {
return null;
}
public void remove() {
}

}
}

*注意事项:迭代器在使用的时候,有人为了方便,如下使用就会有问题  System.out.println(((Student)it.next()).getName()+”---”+((Student)it.next()).getAge());

三、List接口

1、List概述

 * List接口概述
 * 有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。
 * 用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。
 * 与 set 不同,列表通常允许重复的元素。

2、List的特点

 * |--List(接口):1.可以存储重复的;2.有序的(取出时的顺序同存入时)
 * 特有方法:
 * void add(int index,E element):将element添加到index位置;原index位置上元素依次后移;
 * E remove(int index):移除index位置上的元素
 * E get(int index):获取index位置上的元素
 * E set(int index,E element):将element替换原index位置上的元素;
 * 
 * ListIterator listIterator():获取List的迭代器。ListIterator是Iterator的子接口;
 * 跟Iterator的不同:
 * 1.Iterator:单项的迭代器。只能向下遍历;
 * 2.ListIterator:双向的迭代器,可以向上遍历;注意:在向上遍历前,一定要先向下遍历;
 * |--Set(接口):1.不能存储重复元素;2.无序的;

public class Demo {
public static void main(String[] args) {
//1.实例化一个集合
List list = new ArrayList();
list.add("张三");
list.add("李四");
list.add("王五");
Iterator it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//在"李四"之前,插入一个"赵七"
list.add(1,"赵七");
System.out.println("list :" + list);

//移除"赵七"
list.remove(1);
System.out.println("移除赵七后:" + list);

//获取王五
System.out.println("获取王五:" + list.get(2));

//将王五替换为赵七
list.set(2, "赵七");
System.out.println("将王五替换为赵七后:" + list);

//结合Collection的size()和List的get()方法,可以遍历List类型的集合:
for(int i = 0; i < list.size() ; i++){
System.out.println(list.get(i));
}
System.out.println("-----------------------");
//获取一个ListIterator
ListIterator listIt = list.listIterator();
System.out.println("先向下遍历:");
while(listIt.hasNext()){
System.out.println(listIt.next());
}
System.out.println("向上遍历:");
while(listIt.hasPrevious()){
System.out.println(listIt.previous());
}

System.out.println("=====================");
}
}
黑马程序员——Java基础---集合类(上)

3、小结_Collection接口和List接口

* Collection(接口)
 * |--List(接口):1.有序的;2.可以存储重复元素;
 * |--Set(接口):1.无序的;2.不可以存储重复元素:
 * 
 * Collection(接口)的
 * --基本方法:
 * boolean add(Object e):将参数e添加到集合
 * boolean remove(Object o):将参数o从集合中移除
 * void clear():清空集合
 * boolean contains(Object o):基于equals()进行判断;
 * boolean isEmpty():判断集合是否为空
 * int size():集合中元素的数量;
 * --批量的方法:
 * boolean addAll(Collection c):将参数集合,一次性全部添加到当前集合
 * boolean removeAll(Collection c):移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作
 * boolean containsAll(Collection c):如果此 collection 包含指定 collection 中的所有元素,则返回 true
 * boolean retainAll(Collection c):移除此 collection 中未包含在指定 collection 中的所有元素。 
 * --遍历方式:
 * 1.toArray():
 * 2.Iterator():
 * List(接口)的:
 * --新增的方法:
 * void add(int index,E element)
 * E remove(int index)
 * E get(int index)
 * E set(int index,E element)
 * ListIterator listIterator()
 * --遍历的方式:
 * 1.结合使用Collection的size()和List接口的get()方法,使用for循环进行遍历;
 * 2.ListIterator迭代器:可以向下遍历,也可以向上遍历;

4、并发修改异常
 * 1.Iterator:remove()方法不会触发并发修改异常;
 * 2.ListIterator:remove()方法不会触发并发修改异常;
 *                set()方法不会触发并发修改异常;
 *                add()方法不会触发并发修改异常;
 * 3.当使用迭代器遍历元素时,通过List的对象去修改元素内容时,会引发并发修改异常:ConcurrentModificationException
 *   解决:
 *   使用迭代器遍历,如果要修改集合,就要通过迭代器去修改。不要通过List对象修改;

public class Demo {
public static void main(String[] args) {
List list = new ArrayList();
list.add("张三");
list.add("李四");
list.add("王五");

ListIterator listIt = list.listIterator();
while(listIt.hasNext()){
String str = (String)listIt.next();
System.out.println(str);
if(str.equals("李四")){
//listIt.remove();//OK的
listIt.set("赵七");//OK的
//listIt.add("赵七");//OK的
//list.add("赵七");//并发修改异常:通过List对象去修改的;
}
}
System.out.println("----------------------");
Iterator it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
黑马程序员——Java基础---集合类(上)

5、使用List存储自定义对象并遍历

class Student {
String name;
int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
public class Demo {
public static void main(String[] args) {
List list = new ArrayList();
list.add(new Student("张三",20));
list.add(new Student("李四",22));
list.add(new Student("王五",24));
list.add(new Student("周六",26));

//遍历:
//1.toArray();
//2.Iterator();
//3.size()和get()方法:
//4.ListIterator():

for (int i = 0; i < list.size(); i++) {
Student stu = (Student)list.get(i);
System.out.println(stu.name + "," + stu.age);
}
}
}
黑马程序员——Java基础---集合类(上)

6、自定义集合类_数组实现

class Student {
String name;
int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
class MyArrayList {
//内部使用数组存储对象
private Object[] objArray = new Object[2];
private int index = 0;//当前数组可用的索引
public void add(Object obj){
objArray[index] = obj;
index++;
//判断数组是否已被填满
if(index == objArray.length){
System.out.println("数组已满,扩容......");
//数组已满,对数组扩容;定义一个新数组,长度设定为原长度的一倍,将原数组中的所有元素复制到新数组中,然后将引用赋给objArray
//1.定义一个新数组
Object[] newObjArray = new Object[objArray.length * 2];
//2.复制数组
System.arraycopy(objArray, 0, newObjArray, 0, objArray.length);
//3.将新数组的引用赋给objArray
objArray = newObjArray;
}
}
public int size(){
return index;
}
public Object get(int index){
return objArray[index];
}
}
public class Demo {
public static void main(String[] args) {
MyArrayList list = new MyArrayList();
list.add(new Student("张三",20));
list.add(new Student("李四",22));
list.add(new Student("王五",24));
for(int i = 0;i < 3 ;i ++){
list.add(new Student("",20));
}
System.out.println("集合的长度:" + list.size());
//遍历集合
for(int i = 0 ;i < list.size() ; i++){
Student stu = (Student)list.get(i);
System.out.println(stu.name + "," + stu.age);
}
}
}
黑马程序员——Java基础---集合类(上)

7、自定义集合类_链表实现

class Box {
Object obj;
Box next;
public Box(Object obj, Box next) {
super();
this.obj = obj;
this.next = next;
}
}
class MyLinkedList {
private Box firstBox;
private int index;//5
public void add(Object obj){
Box box = new Box(obj,null);
index++;

if(this.firstBox == null){//第一次存储
firstBox = box;
return;
}else{
//遍历链表,找到最后一个链
Box tempBox = this.firstBox;
while(tempBox.next != null){
tempBox = tempBox.next;
}
//上述循环结束后,tempBox存储的就是最后一个链
tempBox.next = box;

}
}

public int size(){
return this.index;
}
public Object get(int index){//类似于数组的索引,从0开始:index = 2(第三个元素)
if(index >= this.index){
return null;
}
int n = 0;
Box tempBox = this.firstBox;
while(n < index){//0 < 2//1 < 2//2 < 2
tempBox = tempBox.next;
n++;
}
return tempBox.obj;
}

}
public class Demo {
public static void main(String[] args) {
MyLinkedList list = new MyLinkedList();
list.add("张三1");
list.add("张三2");
list.add("张三3");
list.add("张三4");
list.add("张三5");
System.out.println(list.get(2));
}
}
黑马程序员——Java基础---集合类(上)

8、常见数据结构(图解)

 * 栈、队列、数组、链表、树、哈希表

 * 面试前要知道的一个知识点:
 * 常见的数据结构的优缺点

黑马程序员——Java基础---集合类(上)

黑马程序员——Java基础---集合类(上)

黑马程序员——Java基础---集合类(上)

二、List的三个子类知识详解

1、List接口的三个子类

 * |--List(接口):1.有序的;2.可以存储重复值
 * |--ArrayList(类):1.数组实现;2.不是同步的(不保证线程安全),效率高;
 * |--Vector(类):1.数组实现;2.同步的(线程安全的),效率低
 * |--LinkedList(类):1.链表实现;
 * 数组结构:查询快,增、删慢;
 * 链表结构:查询慢,增、删快;
 * |--Set(接口):1.无序的;2.不能存储重复值

2、ArrayList存储自定义对象并遍历

class Student {
String name;
int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
public class Demo {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(new Student("张三",20));
list.add(new Student("李四",22));
list.add(new Student("王五",24));
list.add(new Student("周六",26));
list.add(new Student("周六",26));

//遍历:四种:
//toArray();
//Iterator;
//get();
//ListIterator

//使用第三种
for(int i = 0;i < list.size() ; i++){
Student stu = (Student)list.get(i);
System.out.println(stu.name + "," + stu.age);
}

}
}
黑马程序员——Java基础---集合类(上)

3、Vector存储自定义对象并遍历

 * Collection:
 * |--List:
 * |--Vector:数组实现;同步的(线程安全的),效率低;
 * 特有方法
 * public void addElement(E obj):添加一个元素;(相当于Collection的add()方法)
 * public E elementAt(int index):获取index位置上的元素;(相当于List的get()方法)

public class Student {
String name;
int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
public class Demo {
public static void main(String[] args) {
//1.实例化一个Vector
Vector vec = new Vector();
//2.填充集合
vec.add(new Student("刘德华",20));
vec.add(new Student("张学友",22));
vec.addElement(new Student("章子怡",18));
vec.addElement(new Student("汪峰",80));

//3.遍历
for(int i = 0;i < vec.size() ; i++){
Student stu = (Student)vec.elementAt(i);
//Student stu = (Student)vec.get(i);
System.out.println(stu.name + "," + stu.age);
}

}
}
黑马程序员——Java基础---集合类(上)

4、LinkedList集合
 * Collection:
 * |--List:
 * |--LinkedList:链表实现。非同步的(线程不安全的),效率高;
 * 特有功能
 * public void addFirst(E e)及addLast(E e):
 * public E getFirst()及getLast()
 * public E removeFirst()及public E removeLast()

public class Demo {
public static void main(String[] args) {
LinkedList list = new LinkedList();
//list.add("aaa");
//list.add("bbb");
//list.add("ccc");

list.addFirst("aaa");
list.addFirst("bbb");
list.addFirst("ccc");

for(int i = 0;i < list.size() ; i++){
//System.out.println(list.get(i));
System.out.println(list.getLast());
//System.out.println(list.getFirst());
//list.removeLast();
//i--;
}
}
}
黑马程序员——Java基础---集合类(上)

5、去除ArrayList中重复的元素(练习)

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

public boolean equals(Object obj){
Student stu = (Student)obj;
return this.name.equals(stu.name) &&
this.age == stu.age;
}
}
public class Demo {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(new Student("李四",22));
list.add(new Student("李四",22));
list.add(new Student("李四",22));
list.add(new Student("张三",20));
list.add(new Student("李四",22));
list.add(new Student("李四",22));
list.add(new Student("王五",24));
list.add(new Student("王五",24));
list.add(new Student("王五",24));
list.add(new Student("王五",24));
list.add(new Student("王五",24));

//方式一:
ArrayList newList = new ArrayList();
System.out.println(newList.size());

//遍历
loop:
for(int i = 0;i < list.size() ;i++){
Student stu = (Student)list.get(i);
for(int j = 0;j < newList.size() ; j++){
Student stu2 = (Student)newList.get(j);
if(stu.equals(stu2)){
continue loop;
}
}
//将stu添加到newList中
newList.add(stu);
}

//遍历newList
for(int i = 0 ;i < newList.size() ; i++){
Student stu = (Student)newList.get(i);
System.out.println(stu.name + "," + stu.age);
}

//方式二:
/*for(int i = 0; i < list.size() - 1 ; i++){
Student stu1 = (Student)list.get(i);
for(int j = i + 1 ; j < list.size() ; j++){
Student stu2 = (Student)list.get(j);
if(stu1.equals(stu2)){
list.remove(j);
j--;
}
}
}
//遍历原集合
for(int i = 0; i < list.size() ; i++){
Student stu = (Student)list.get(i);
System.out.println(stu.name + "," + stu.age);
}*/

}
}
黑马程序员——Java基础---集合类(上)

6、用LinkedList模拟栈数据结构的集合并测试(练习)

class MyLinkedList {
private LinkedList list = new LinkedList();

public void add(Object obj){
this.list.addFirst(obj);
}
public Object get(int index){
return this.list.get(index);
}

public int size(){
return this.list.size();
}
}
public class Demo {
public static void main(String[] args) {
MyLinkedList list = new MyLinkedList();

list.add("aaa");
list.add("bbb");
list.add("ccc");

for(int i = 0;i < list.size() ; i++){
System.out.println(list.get(i));
}
}
}
黑马程序员——Java基础---集合类(上)

三、JDK1.5新特性——泛型

1、泛型概述

* 泛型:
 * 1.当我们定义一个集合后,我们可以向集合中添加什么数据?任何的引用类型;
 * 2.当我们取出时,尤其是需要"向下转型"时,会给我们带来很大麻烦;
 * 3.实际上我们开发时,经常只需要一个集合中只存储一种数据类型的引用;
 * 4.这时,Java为我们提供了一种机制:
 * 1).在定义集合时,就强制定义了这个集合中只能存储哪种类型的数据;
 * 2).如果代码中,试图存储其它类型的数据时,编译时,就会发生错误;
 *   这种机制:泛型
 * 5.示例:
 * //定义一个只存储字符串的集合
 * List<String> strList = new ArrayList<String>();
 * 或:
 * List<String> strList = new ArrayList<>();//(常用)
 * 或:
 * List<String> strList = new ArrayList();
 * //存储元素
 * strList.add("abc");//OK的
 * strList.add(20);//编译错误
 * //遍历取出时--不需要强制转换
 * for(int i = 0;i < strList.size(); i++){
 * String str = strList.get(i);
 * }
 * 6.注意:泛型只存在于"编译期",当生成class文件后,就没有泛型信息了;

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

public boolean equals(Object obj){
Student stu = (Student)obj;
return this.name.equals(stu.name) &&
this.age == stu.age;
}
}
public class Demo {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("aaa");
list.add(10);//自动装箱
list.add(true);//自动装箱
list.add(3.14);//自动装箱
list.add(new Student("张三",20));

ArrayList list2 = new ArrayList();
list2.add("aaa");
list2.add("bbb");
list2.add("ccc");
list2.add(new Student("张三",20));

/*for(int i = 0;i < list2.size() ; i++){
//很多时候,我们为了访问所存储对象的"特有成员",经常要向下强转为所存储的类型
String str = (String)list2.get(i);

}*/

//使用泛型定义集合
ArrayList<String> strList = new ArrayList<>();

strList.add("aaa");
//strList.add(20);//编译错误

for(int i = 0;i < strList.size() ; i++){
String str = strList.get(i);
}

ArrayList<Student> stuList = new ArrayList<>();
stuList.add(new Student("张三",20));
for(int i = 0;i < stuList.size() ; i++){
Student stu = stuList.get(i);
System.out.println(stu.name + "," + stu.age);
}
}
}

2、泛型类

 * 泛型类的定义:
 * 1.在"类名后"使用一对<>括号;
 * 2.里面可以定义泛型名称;
 * 3.泛型名称:
 * 1).可以是一个字母;也可以是多个字母;
 * 2).可以小写,可以大写;
 * 3).可以是一个,可以是多个;多个的话使用逗号分隔;

public class MyLinkedList<abc> {
public void add1(abc obj){
}
}
public class Demo {
public static void main(String[] args) {
MyLinkedList<String> list = new MyLinkedList<>();
}
}

3、泛型方法

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

public boolean equals(Object obj){
Student stu = (Student)obj;
return this.name.equals(stu.name) &&
this.age == stu.age;
}
}
public class MyLinkedList {

//接收三个某种类型的数据
//能返回一个具有这种类型泛型的一个集合对象;
public <T> List<T> add1(T obj1,T obj2,T obj3){

List<T> list = new ArrayList<>();
list.add(obj1);
list.add(obj2);
list.add(obj3);
return list;
}
}
public class Demo {
public static void main(String[] args) {
MyLinkedList list = new MyLinkedList();
List<String> strList = list.add1("aaa", "bbb", "ccc");

List<Student> stuList = list.add1(new Student("a",20), new Student("b",22), new Student("c",24));
}
}
4、泛型接口

 * 当子类实现了一个带泛型的接口时:
 * 有三种可选择的操作:
 * 1.丢弃泛型;方法内的泛型部分全部变为Object类型;
 * class SubA implements IA{
 * public void add(Object obj){
 * }
 * }
 * 2.指定一个具体类型:
 * class SubA implements IA<String>{
 * public void add(String str){
 * }
 * }
 * 3.继续支持泛型;(子类常见的方式)
 * class SubA<E> implements IA<E>{
 * public void add(E e){
 * }
 * }

public interface IA <E>{
public void add(E e);
public E get(int index);
}
public class SubA<E> implements IA<E> {
@Override
public void add(E e) {
// TODO Auto-generated method stub

}
@Override
public E get(int index) {
// TODO Auto-generated method stub
return null;
}
}
public class Demo {
ArrayList list;
}

5、泛型通配符

 * 泛型通配符
 * 1.<?> : 
 * 1).变量可以指向什么类型的对象:具有任何泛型的集合对象;
 * 2).可以存储什么东西:由于?不确定具体类型,所以不能add()任何类型
 * 3).取出时用什么接收:只能用Object接收;
 * 作用:不能存入,只能获取,所以一般用作方法的返回值声明;
 * 2.<? extends E> :
 * 1).变量可以指向什么类型的对象:具有E泛型或者E子类泛型的集合;
 * 2).可以存储什么东西:由于不确定是哪个E的子类,所以不能存任何东西;
 * 3).取出时用什么接收:只能用E及E的父类类型接收;
 * 3.<? super E> : 
 * 1).变量可以指向什么类型的对象:具有E泛型或者E父类泛型的集合;
 * 2).可以存储什么东西:只能存储E或者E的子类对象;
 * 3).取出时用什么接收:由于存储的可能是任何的E的子类对象,所以只能用Object接收;

class Animal{}
class Cat extends Animal{};
class Dog extends Animal{};
class JMDog extends Dog{};
public class Demo {
public static void main(String[] args) {
//1.<?>
List<?> list1 = new ArrayList<>();
List<?> list2 = new ArrayList<String>();
List<?> list3 = new ArrayList<Animal>();
//
//list2.add("aa");
//list2.add(10);
//list2.add(new Animal());

Object obj = list2.get(0);

//2.<? extends E>
//List<? extends Dog> list4 = new ArrayList<Animal>();//编译错误
List<? extends Dog> list5 = new ArrayList<Dog>();
List<? extends Dog> list6 = new ArrayList<JMDog>();
/*
list5.add("你好");
list5.add(10);
list5.add(new Animal());
list5.add(new Dog());
list5.add(new JMDog());
*/
Dog d1 = list5.get(0);
Animal a1 = list5.get(0);

//3.<? super E>
List<? super Dog> list7 = new ArrayList<Animal>();
List<? super Dog> list8 = new ArrayList<Dog>();
//List<? super Dog> list9 = new ArrayList<JMDog>();

//list7.add(new Animal());
list7.add(new Dog());
//list7.add(new Cat());
list7.add(new JMDog());
Object d = list7.get(0);
}
}

六、JDK5.0新特性——foreach循环

1、增强for循环(forEach循环)概述

 * 1.可以遍历数组,可以遍历集合
 * 2.格式:
 * int[] array = {143,32,5,234,32,4};
 * for(int i = 0;i < array.length ; i++){
 * int n = array[i];
 * System.out.println(n);
 * }
 * //使用增强for
 * for(int n : array){
 * System.out.println(n);
 * }
 * 3.特点:不需要使用"循环变量";
 *  4.当不需要使用循环变量时:只是简单的从头遍历元素到末尾,这时可以选择:增强for语句;
 *    如果遍历时,需要使用循环变量,那么就使用普通for循环;

public class Demo {
public static void main(String[] args) {
int[] array = {1,432,4325,4324,13,435};
for(int n : array){
System.out.println(n);
}
//遍历集合时,被编译成了"迭代器的方式",会可能产生并发修改异常;
List<String> strList = new ArrayList<>();
strList.add("aaa");
strList.add("bbb");
strList.add("ccc");

for(String s : strList){
System.out.println(s);
if(s.equals("bbb")){
strList.add("ddd");
}
}
}
}
黑马程序员——Java基础---集合类(上)

2、ArrayList存储自定义对象并遍历增强for版(练习)

public class Student {
String name;
int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
public class Demo {
public static void main(String[] args) {
List<Student> stuList = new ArrayList<>();
stuList.add(new Student("刘德华",20));
stuList.add(new Student("刘亦菲",22));
stuList.add(new Student("刘备",24));

//使用增强for遍历
for(Student stu : stuList){
System.out.println(stu.name + "," + stu.age);
}
}
}
黑马程序员——Java基础---集合类(上)

七、静态导入的概述和使用

 * 静态导入概述
 * 格式:import static 包名….类名.方法名;
 * 可以直接导入到方法的级别
 * 注意事项
 * 方法必须是静态的
 * 如果有多个同名的静态方法,容易不知道使用谁?这个时候要使用,必须加前缀。由此可见,意义不大,所以一般不用,但是要能看懂。
 * 
 * *当我们需要很频繁的使用到某个类中的某个,或者某些静态方法时, 我们需要通过"类名.方法名()"来访问.
 * *如果频繁调用,可以使用"静态导入",先将方法导入,后使用,使用时不需要使用类名;

import static java.lang.Math.max;//注意:导入的"方法名"
import static java.lang.Math.*;//可以使用通配符
public class Demo {
public static void main(String[] args) {
System.out.println(max(10, 20));
System.out.println(max(2324, 43392));
System.out.println(max(243, 3532));
}
}
八、 可变参数:
 * 1.在定义方法时,某些形参,如果不确定其数量时,可以指定为:可变参数;
 * 2.格式:数据类型 ... 变量名;
 * 3.在方法内,对于可变参数,是按照"数组"的方式进行处理的;
 * 4.注意:在方法的形参列表内,可以同时指定可变参数和普通参数,可变参数要位于参数列表的末尾;

class MyMath{
//求两个整数的和
/*public static int sum(int a ,int b){
return a + b;
}
public static int sum(int a , int b,int c){
return a + b + c;
}*/
/*
public static int sum(int[] array){
int sum = 0;
for(int n : array){
sum+=n;
}
return sum;
}
*/
//可变参数
public static int sum(int ...nums ){
//可变参数在内部,以数组的方式处理
int sum = 0;
for(int i = 0;i < nums.length ; i++){
sum+=nums[i];
}
return sum;
}
}
public class Demo {
public static void main(String[] args) {
System.out.println(MyMath.sum(10, 20));
System.out.println(MyMath.sum(10,20,30));
int[] array = {1432,32,43,24,314,35};
System.out.println(MyMath.sum(array));

System.out.println(MyMath.sum(4325,42,432,5,24,321,432,53,62,5,36,5,34,513,432));
}
}
黑马程序员——Java基础---集合类(上)

九、Arrays类

Arrays类的_asList方法_将数组转换为集合

 * Arrays类的asList()方法:将数组转换为集合
 * 获取的集合:不能添加,不能删除;可以修改元素;

public class Demo {
public static void main(String[] args) {
List<String> strList = Arrays.asList("张三","李四","王五","周六");
List<Integer> intList = Arrays.asList(10,2,34,2,5,4,34,2);
System.out.println("strList = " + strList.getClass().getName());
for(String s : strList){
System.out.println(s);
}
//添加一个元素
//strList.add("赵七");//不能添加;运行时异常;
//strList.remove(0);//不能删除元素;运行时异常;
strList.set(0, " ");//可以修改元素;
System.out.println("集合:" + strList);
}
}
黑马程序员——Java基础---集合类(上)

十、集合嵌套之ArrayList嵌套ArrayList

 * 集合嵌套之ArrayList嵌套ArrayList
 * 
 * 一个班的学员:
 * 刘德华
 * 张学友
 * 郭富城
 * 黎明
 * 另一个班的学员:
 * 章子怡
 * 范冰冰
 * 李宇春
 * 罗玉凤
 * 
 * 将上述两个集合添加到一个大集合中;

public class Demo {
public static void main(String[] args) {
List<String> class1List = new ArrayList<>();
class1List.add("刘德华");
class1List.add("张学友");
class1List.add("郭富城");
class1List.add("黎明");

List<String> class2List = new ArrayList<>();
class2List.add("章子怡");
class2List.add("范冰冰");
class2List.add("李宇春");
class2List.add("罗玉凤");

List<List<String>> list = new ArrayList<>();
list.add(class1List);
list.add(class2List);

for(List<String> classList : list){
for(String s : classList){
System.out.println(s);
}
}


}
}
黑马程序员——Java基础---集合类(上)

总结:

集合类的包:java.util.Xxxx

一.类层次结构:

   Collection(接口)

         |--List(接口):1.有序的;2.可以存储重复值;

             |--ArrayList(类):数组实现;

         |--Set(接口):1.无序的;2.不能存储重复值;

二.Collection接口的常用方法:

         1).基本方法:

                   boolean add(Object e):将参数e添加到集合

                   boolean remove(Object o):将参数o从集合中移除

                   void clear():清空集合

                   boolean contains(Object o):基于equals()进行判断;

                   boolean isEmpty():判断集合是否为空

                   int size():集合中元素的数量;

         2).批量方法:

                   boolean addAll(Collection c):将参数集合,一次性全部添加到当前集合

                   boolean removeAll(Collection c):移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作

                   boolean containsAll(Collection c):如果此 collection 包含指定 collection 中的所有元素,则返回 true

                   boolean retainAll(Collection c):移除此 collection 中未包含在指定 collection 中的所有元素。

         3).遍历的方式:

                   A.toArray();

                   B.Iterator();

三.List接口的常用方法:

         1).新增的方法:

                   void add(int index,E element)

                   E remove(int index)

                   E get(int index)

                   E set(int index,E element)

                   ListIterator listIterator()

         2).遍历的方式:

                   A.结合Collection的size()和List的get()方法,使用for()循环;

                   B.ListIterator:可以向前遍历,也可以向后遍历;

四.Iterator 和 ListIterator的区别:

         1.ListIterator是Iterator的子接口;

         2.Iterator只能向下遍历;

         3.ListIterator可以双向遍历;

 

五.并发修改异常:

         当我们使用迭代器遍历集合时,如果通过集合对象修改集合内的元素,

         这时,会导致并发修改异常;

                   Listlist = new ArrayList();

                   list.add("aaa");

                   list.add("bbb");

                   list.add("ccc");

                   Iteratorit = list.iterator();

                   while(it.hasNext()){

                            Stringstr = (String)it.next();

                            if(str.equals("bbb")){

                                     list.add("ddd");//此处会引发并发修改异常

                            }

                   }

六.数据结构:

         1.栈:先进后出

         2.队列:先进先出

         3.数组:随机获取元素快,增、删慢;

         4.链表:查询慢,增、删非常快;

七:ArrayList:

         1).没有特有方法,都是使用的父接口中定义的;

  Vector类:

  LinkedList类:

八:泛型:

         1.在定义集合时,可以指定这个集合内只能装什么类型元素,这种方式就是“泛型”

                   ArrayList<String>strList = new ArrayList<String>();

                   或:

                   ArrayList<String>strList = new ArrayList<>();

                   或:

                   ArrayList<String>strList = new ArrayList();

         2.泛型类:class MyArrayList<T>{}

                 1.T:可以是任何字母;大小写都可以;

                 2.也可以定义多个泛型,中间用逗号隔开;<T,V>

         3.泛型方法:

                   classMyArrayList{

                            //接收的是什么类型,返回的就是具有这个类型

                            public<T> T show(T t){

                                     returnt;

                            }

                   }

         4.泛型接口:

                   interfaceIA<T>{

                            Tshow(T t);

                   }

           子类实现时:

                   1.可以继续定义泛型:

                            classA <T> implements IA<T>{

                                     publicT show(T t){

                                     }

                            }

                   2.可以固定为某个具体类型

                            classA  implements IA<String>{

                                     publicString show(String s){

                                     }

                            }

                   3.可以将泛型丢弃

                            classA implements IA{

                                     publicObject show(Object o){

                                     }

                            }

         5.泛型的通配符:见Demo

                   1:<?>:

                   2:<?extends E>:

                   3:<?super E>:

九:静态导入:

         1.如果需要很频繁的使用某个类中某些静态方法,可以一次性导入这些静态方法,

         或者导入某个静态方法,导入后,使用这些方法时,不用类名,直接使用即可;

            import static java.lang.Math.abs;

            import static java.lang.Math.*;

十:可变参数:

         1.一个方法如果不确定需要多少个参数,可以定义为:可变参数;

         2.可变参数,跟数组是一样的,所以不能"数组"的方法;

         3.在方法内部,对于可变参数,就是用数组的方式去操作;

         4.在编译后,可变参数的声明,就变成了数组的声明;

         5.调用可变参数的方法:可以不传递实参;

十一:Arrays类的asList()方法;

         1.能够返回具有形参类型的集合对象,内部已经封装了所有的实参;

十二:集合的嵌套:

         1.一个集合内可以嵌套另一个集合;

         2.遍历时要注意,每一层从集合中取出的是什么样的集合;