------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------
集合类知识目录:
一、集合概述
1、对象数组的概述和使用
2、对象数组的内存(图解)
3、集合的由来及集合的继承体系图
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));
}
}
2、对象数组的内存(图解)
3、集合的由来及集合的继承体系图
* 为什么出现集合类?
* 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,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对象,使用数据,一旦定义长度,之后就不能改变;
//所以,如果我们使用"集合"存储,我们就不用关心长度的问题;
}
}
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);
}
}
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());
}
}
}
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());
}
}
}
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("=====================");
}
}
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());
}
}
}
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);
}
}
}
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);
}
}
}
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));
}
}
8、常见数据结构(图解)
* 栈、队列、数组、链表、树、哈希表
* 面试前要知道的一个知识点:
* 常见的数据结构的优缺点
二、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);
}
}
}
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);
}
}
}
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--;
}
}
}
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);
}*/
}
}
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));
}
}
}
三、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 {4、泛型接口
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));
}
}
* 当子类实现了一个带泛型的接口时:
* 有三种可选择的操作:
* 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");
}
}
}
}
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);
}
}
}
七、静态导入的概述和使用
* 静态导入概述
* 格式: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));
}
}
九、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);
}
}
十、集合嵌套之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.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.遍历时要注意,每一层从集合中取出的是什么样的集合;