集合、迭代器、增强for循环、泛型

1集合

集合是java中提供的一种容器,可以用来存储多个数据。

数组的长度是固定的。集合的长度是可变的。集合中存储的元素必须是引用类型数据。

1.1ArrayList集合存储元素(复习)

例:

public class Person {
	private String name;
	private int age;
	public Person() {
		super();
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	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;
	}	
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}	
}
import java.util.ArrayList;
public class Test1 {
	public static void main(String[] args) {
		//集合复习:存储基本数据类型
		ArrayList<Double> arr1=new ArrayList<Double>();
		arr1.add(1.6);
		arr1.add(2.3);
		arr1.add(3.6);
		
		for(int i=0;i<arr1.size();i++){
			System.out.print(arr1.get(i)+" ");
		}
		
		System.out.println();
		
		//集合存储引用数据类型
		ArrayList<Person> arr2=new ArrayList<Person>();
		arr2.add(new Person("张三",18));//存匿名对象
		arr2.add(new Person("小红帽",8));
		arr2.add(new Person("大灰狼",55));
		
		for(int i=0;i<arr2.size();i++){
			System.out.println(arr2.get(i)); //调用toString方法,已重写
		}
	}
}

1.2集合的继承实现关系

常用的:

1.3 Collection接口

 

Collection接口是集合中的顶层接口,它中定义的所有功能子类都可以使用。

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

(这里的有序不是指元素在值上的排序,而是指存、取的顺序一致,怎么存就怎么取,有索引下标)

1.3.1 Collection常用方法

Collection是接口,所以全是抽象方法。

需要用多态new对象。

例:

import java.util.Collection;
import java.util.ArrayList;

public class CollectionTest {
	public static void main(String[] args) {
		//创建对象
		Collection<String> col=new ArrayList<String>();
		
		//添加元素
		col.add("中国");
		col.add("你好");
		col.add("java");
		
		//判断集合中是否包含某元素
		boolean flag=col.contains("java");	
		if(flag){
			System.out.println("true,包含元素");
		}		
		
		//移除元素
		boolean dels=col.remove("你好"); //这个是返回布尔值
		if(dels){
			System.out.println("移除成功");
		}		
		
		//向下转型
		ArrayList<String> arr=null; //定义成全局,不然遍历时取不到
		if(col instanceof ArrayList){
			arr=(ArrayList<String>)col;
		}
		
		System.out.println();
		
		//遍历		
		System.out.println("遍历结果:");
		for(int i=0;i<arr.size();i++){
			System.out.print(arr.get(i)+" ");			
		}
		
		System.out.println();
		System.out.println();
		
		//转成数组
		Object[] strs=col.toArray();		
		System.out.println("遍历数组:");
		for(int i=0;i<strs.length;i++){
			//String str=(String)strs[i];//这里是Object型数组,如果想转成String数组,不能直接强转,要给元素转型
			System.out.print(strs[i]+" ");			
		}
		
		System.out.println();
		System.out.println();
		
		//清除内容
		col.clear();		
		System.out.println("清除后:");
		for(int i=0;i<arr.size();i++){
			System.out.print(arr.get(i)+" ");			
		}		
	}
}

注意:

1注意方法的返回值类型

2一定要指定泛型,不然还要强转

例:会有警告

 

1.4 Iterator迭代器

1.4.1定义

java中提供了很多个集合,它们在存储元素时,采用的存储方式不同。

List有序(有下标索引),set无序(看上面的继承体系图)

要取出这些集合中的元素,可通过一种通用的获取方式来完成。

迭代定义:

Collection集合元素的通用获取方式:在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。

集合中把这种取元素的方式描述在Iterator接口中。

1.4.2 Iterator接口的常用方法

 

hasNext()方法:用来判断集合中是否有下一个元素可以迭代。如果返回true,说明可以迭代。

next()方法:用来返回迭代的下一个元素,并把指针向后移动一位。

1.4.3 Iterator接口的对象

 

Iterable对象里有一个iterator() 方法,可以返回Iterator对象,Collection继承了这个方法,那么其子类或实现类就都有了这个方法,可以用这个方法创建Iterator对象。

 

例:(Iterator接口也可以使用<>来控制迭代元素的类型的

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class IteratorTest {
	public static void main(String[] args) {
		Collection<Integer> col=new ArrayList<Integer>();
		col.add(1);
		col.add(2);
		col.add(3);
		col.add(4);
		
		//获取迭代器对象	
		Iterator<Integer> it=col.iterator();
		
		//循环
		while(it.hasNext()){
			int i=it.next(); //自动拆箱
			System.out.println(i);
		}		
	}
}

注意:

1next()只能用一次,再调用,指针还会往后走,想判断,要先把值获取到,再判断值。

例:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class I2 {
	public static void main(String[] args) {
		Collection<Integer> col=new ArrayList<Integer>();
		col.add(1);
		col.add(2);
		col.add(3);
		col.add(4);
		
		//获取迭代器对象	
		Iterator<Integer> it=col.iterator();		
		
		//用循环
		while(it.hasNext()){
			if(it.next()==2){
				System.out.println(it.next());
			}
		}		
	}
}

说明next()又向后走了,所以要改成这样:

while(it.hasNext()){
int i=it.next();
	if(i==2){
		System.out.println(i);
	}			
}	

还可以for循环,但不常用

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class I2 {
	public static void main(String[] args) {
		Collection<Integer> col=new ArrayList<Integer>();
		col.add(1);
		col.add(2);
		col.add(3);
		col.add(4);
		
		for(Iterator<Integer> it=col.iterator();it.hasNext();){
			System.out.println(it.next());
		}		
	}
}

2)在进行集合元素取出时,如果集合中已经没有元素了,还继续使用迭代器的next方法,将会发生java.util.NoSuchElementException没有集合元素的错误。

例:

 

1.5集合元素的向下转型

集合中可以存储任何对象,那么存放进去的数据就不再是原来类型了,而是提升成了Object

如果集合中存放的是多个对象,这时进行向下转型会发生类型转换异常。

 

 

3增强for循环

增强for循环是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。

3.1格式:

for(元素的数据类型 变量 : Collection集合or数组){

}

例:

import java.util.ArrayList;
import java.util.Collection;

public class forTest {
	public static void main(String[] args) {
		Collection<String> col=new ArrayList<String>();
		col.add("你好");
		col.add("快乐");		
		
		//使用增强for
		for(String str:col){
			System.out.println(str); //取到的就是String对象
		}
		
		//使用增强for遍历数组
		int[] arr={1,2,3,4,5};
		for(int i:arr){
			System.out.print(i+" "); //i就是每个值
		}
	}
}

3.2对比:

1迭代器只能迭代集合,增强for能遍历集合和数组。

2for循环必须有被遍历的目标。目标只能是Collection或者是数组。只用来遍历,不进行任何操作。

遍历数组时,如果仅为遍历,可以使用增强for。

如果要对数组的元素进行操作,使用老式for循环,(因为可以通过标操作

3.3总结:

遍历集合:三种方式

遍历数组:两种方式

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Test1 {
	public static void main(String[] args) {
		showList();
		showArr();
	}
	
	public static void showList(){
		Collection<String> col=new ArrayList<String>();
		col.add("abc");
		col.add("ABC");
		col.add("12345");
		
		//for循环遍历
		System.out.println("for循环遍历集合:");
		ArrayList<String> arr=null;
		if(col instanceof ArrayList){
			arr=(ArrayList<String>)col;
		}
		for(int i=0;i<arr.size();i++){
			System.out.print(arr.get(i)+"	");
		}
		
		//迭代器
		System.out.println();
		System.out.println("迭代器集合:");
		Iterator<String> it=col.iterator();
		while(it.hasNext()){
			System.out.print(it.next()+"	");
		}
		
		//增强for
		System.out.println();
		System.out.println("增强for遍历集合:");
		for(String str:col){
			System.out.print(str+"	");
		}
	}
	
	public static void showArr(){
		System.out.println();
		int[] arr={1,2,3,4,5};
		
		System.out.println("普通for遍历数组:");
		for(int i=0;i<arr.length;i++){
			System.out.print(arr[i]+" ");
		}
		
		System.out.println();
		System.out.println("增强for遍历数组:");
		for(int i:arr){
			System.out.print(i+" ");
		}		
	}
}

4泛型

前面一些例子,集合中是可以存放任意对象的提升成Object类型,这时容易发生

ClassCastException类型转换异常,泛型就是为了解决这个问题。

4.1定义

使用集合时,必须明确集合中元素的类型这种方式称为泛型。

泛型,用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数进行传递。

定义格式:

修饰符 class 类名<代表泛型的变量> { }

修饰符 interface接口名<代表泛型的变量> { }

E就是一个变量,是element的意思,在什么时候明确:

1)实现或继承时明确

Public class MyList<String> implements list<E>{}

Public class MyList<E> implements list<String>{}

2new对象时明确

Api中带<E>的方法都是如此

4.2使用泛型的好处

将运行时期的ClassCastException,转移到了编译时期变成了编译失败。避免了类型强转的麻烦。

Tips:

泛型:又叫伪泛型,编译时不进.class文件   (注释也不进)

只在java代码中对集合存储数据类型进行约束

4.3泛型通配符

定义方法时,无法确定具体集合中的元素类型是什么,可以使用泛型通配符<?>,用来占空。

例:

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

public class Test02 {
	public static void main(String[] args) {
		ArrayList<String> arr=new ArrayList<String>();
		arr.add("中国");
		arr.add("java");
		
		HashSet<Integer> set=new HashSet<Integer>();
		set.add(1);
		set.add(2);
		
		showAll(arr);
		showAll(set);
	}
	
	//泛型通配符
	public static void showAll(Collection<?> col){
		Iterator<?> it=col.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
}

但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用。(可以向下转型,但是太麻烦了)

4.4泛型限定

泛型里面没有向上向下转型的概念。所以要定好。

限定泛型的上限:

格式:? extends E

? 代表接收E类型或者E的子类型的元素

限定泛型的下限:

格式:? super E

? 代表接收E类型或者E的父类型的元素(父类型,不只是父类)

例:

//员工类
public abstract class Emp {
	public abstract void work();
}
//经理类
public class Manager extends Emp{	
	public void work() {
		System.out.println("经理管理");		
	}
}
//服务员类
public class Waiter extends Emp{	
	public void work() {
		System.out.println("服务员上菜");		
	}
}
//厨师类
public class Cooker extends Emp{	
	public void work() {
		System.out.println("厨师炒菜");		
	}
}

  

import java.util.ArrayList;

public class Test03 {
	//四个类:员工,经理,服务员,厨师 都有work方法
	//传入三个类调用其work方法	
	public static void main(String[] args) {		
		Manager m=new Manager();
		ArrayList<Manager> arr1=new ArrayList<Manager>();
		arr1.add(m);
		
		Waiter w=new Waiter();
		ArrayList<Waiter> arr2=new ArrayList<Waiter>();
		arr2.add(w);
		
		Cooker c=new Cooker();
		ArrayList<Cooker> arr3=new ArrayList<Cooker>();
		arr3.add(c);
		
		working(arr1); 
		working(arr2);
		working(arr3);
		
		ArrayList<Object> arr4=new ArrayList<Object>();
		arr4.add("这是一个Object类型的数据");
		arr4.add("这是一个Object类型的数据2");
		working2(arr4);
		
	}
	public static void working(ArrayList<? extends Emp> arr){ //限定泛型的上限
		Emp emp=arr.get(0);
		emp.work();
	}
	
	public static void working2(ArrayList<? super Emp> arr){ //限定泛型的下限
		for(int i=0;i<arr.size();i++){
			System.out.println(arr.get(i));
		}
	}	
}

这里如果是接口,也可以用extends。

原文地址:https://www.cnblogs.com/hzhjxx/p/10094131.html