目录

  • 什么是集合
  • Collection
  • Collection系列的3种集合遍历


集合框架图:

java 如何循环遍历枚举值是否相等_数据结构

什么是集合

集合是一个可以封装并管理对象的容器(基本数据类型存入的是封装类),且容器都具有其自己的操作标准(对于对象的增删改查等等)。

MyArrayList我们自己设计的一种数据结构,一种逻辑结构,当别人用我这个MyArrayList的对象时,就是一个容器对象,
可以用来装对象。

public class MyArrayList {
	//为什么使用Object,因为只是说这个容器是用来装对象的,但是不知道用来装什么对象。
	private Object[] data;
	private int total;
	
	public MyArrayList(){
		data = new Object[5];
	}
	
	//添加一个元素
	public void add(Object obj){
		//检查是否需要扩容
		checkCapacity();
		data[total++] = obj;
	}

	private void checkCapacity() {
		//如果data满了,就扩容为原来的2倍
		if(total >= data.length){
			data = Arrays.copyOf(data, data.length*2);
		}
	}
	
	//返回实际元素的个数
	public int size(){
		return total;
	}
	
	//返回数组的实际容量
	public int capacity(){
		return data.length;
	}
	
	//获取[index]位置的元素
	public Object get(int index){
		//校验index的合理性范围
		checkIndex(index);
		return data[index];
	}

	private void checkIndex(int index) {
		if(index<0 || index>=total){
			throw new RuntimeException(index+"对应位置的元素不存在");
//			throw new IndexOutOfBoundsException(index+"越界");
		}
	}
	
	//替换[index]位置的元素
	public void set(int index, Object value){
		//校验index的合理性范围
		checkIndex(index);		
		data[index] = value;
	}
	
	//在[index]位置插入一个元素value
	public void insert(int index, Object value){		
		
		//(1)考虑下标的合理性:校验index的合理性范围
		checkIndex(index);
		
		//(2)总长度是否够:检查是否需要扩容
		checkCapacity();
		
		//(3)[index]以及后面的元素往后移动,把[index]位置腾出来	
		System.arraycopy(data, index, data, index+1, total-index);
		
		//(4)data[index]=value  放入新元素
		data[index] = value;
		
		//(5)total++  有效元素的个数增加
		total++;
	}
	
	//返回所有实际存储的元素
	public Object[] getAll(){
		//返回total个
		return Arrays.copyOf(data, total);
	}
	
	//删除[index]位置的元素
	public void remove(int index){
			
		//(1)考虑下标的合理性:校验index的合理性范围
		checkIndex(index);
		
		//(2)移动元素,把[index+1]以及后面的元素往前移动		
		System.arraycopy(data, index+1, data, index, total-index-1);
		
		//(3)把data[total-1]=null  让垃圾回收器尽快回收
		data[total-1] = null;
		
//		(4)总元素个数减少 total--
		total--;
	}
	
	//查询某个元素的下标
/*	public int indexOf(Object obj){
		for (int i = 0; i < total; i++) {
		//这两种写法都有风险
			if(obj.equals(data[i])){
				//if(data[i].equals(obj)){
				return i;//找到,返回第一个找到的
			}
		}
		return -1;//没找到返回-1
	}*/
	
	//查询某个元素的下标
	public int indexOf(Object obj){
		if(obj == null){
			for (int i = 0; i < total; i++) {
				if(data[i] == null){//等价于 if(data[i] == obj)
					return i;
				}
			}
		}else{
			for (int i = 0; i < data.length; i++) {
				if(obj.equals(data[i])){
					return i;
				}
			}
		}
		return -1;
	}
	
	//删除数组中的某个元素
	//如果有重复的,只删除第一个
	public void remove(Object obj){
		/*
		 * (1)先查询obj的[index]
		 * (2)如果存在,就调用remove(index)删除就可以
		 */
		
		//(1)先查询obj的[index]
		int index = indexOf(obj);
		
		if(index != -1){
			remove(index);
		}
		//不存在,可以什么也不做
		//不存在,也可以抛异常
		//throw new RuntimeException(obj + "不存在");
	}
	
	public void set(Object old, Object value){
		/*
		 * (1)查询old的[index]
		 * (2)如果存在,就调用set(index, value)
		 */
		
//		(1)查询old的[index]
		int index = indexOf(old);
		if(index!=-1){
			set(index, value);
		}
		
		//不存在,可以什么也不做
		//不存在,也可以抛异常
		//throw new RuntimeException(old + "不存在");
	}
}

然而不同集合由于其封装的对象的不同,底部的数据结构支持也就不同,所以就会出现很多种类的集合

比如 ArrayList、HashMap底层数据结构是数组,LinkedList底层数据结构是链表。

对于开发人员来说,这么多的集合无疑会造成很大的学习开销,因此java给这些集合抽取了两大接口:

1.Collection

 规范单值集合的接口——>单身party

2.Map

 规范对值集合的接口,(key,value)——>情侣party

java 如何循环遍历枚举值是否相等_迭代器_02

Collection

(1)它是根接口
(2)它没有直接的实现类,有更具体的子接口:List和Set…
(3)有些集合的元素是可以重复的,有些集合的元素是不能重复,有些集合的元素是有序的,有些集合的元素是无序的。虽然有很多具体的子接口,但是他们具有统一的API:
(1)添加
         add(Object obj):添加一个元素
         addAll(Collection c):添加多个元素

Collection c = new ArrayList();//ArrayList是Collection下面的一个实现类而已
		c.add(1);
		c.add(2);
		c.add(3);
		
Collection c2 = new ArrayList();//ArrayList是Collection下面的一个实现类而已
		c2.add("张三");
		c2.add("李四");
		c2.add("王五");
c.addAll(c2);//把c2中的所有元素都添加到c集合中
System.out.println(c);//[1,2,3,张三,李四,王五]   6个元素
System.out.println( c.size());//6

c.add(c2);
System.out.println(c);//[1,2,3,[张三,李四,王五]]   4个元素

(2)获取有效元素的个数
         int size()
(3)是否包含
         contains(Object o) :判断o是否在当前的集合中
         containsAll(Collection c) :判断c是否是当前集合的子集

Collection c = new ArrayList();//ArrayList是Collection下面的一个实现类而已
		c.add("张三");
		c.add("李四");
		c.add("王五");
System.out.println(c.contains("张三"));//true
System.out.println(c.contains("杨洪强"));//false		
		
		Collection c2 = new ArrayList();//ArrayList是Collection下面的一个实现类而已
		c2.add("张三");
		c2.add("李四");
		
		Collection c3 = new ArrayList();//ArrayList是Collection下面的一个实现类而已
		c3.add("张三");
		c3.add("杨洪强");
		
System.out.println(c.containsAll(c2));//c2是c的子集,true
System.out.println(c.containsAll(c3));//c3不是c的子集,false

(4)判断当前集合是否为空
         boolean isEmpty() , 等价于 集合对象.size()==0
(5)remove(Object o):删除一个
         removeAll(Collection c):删除多个 this = this - this ∩ c

Collection c = new ArrayList();//ArrayList是Collection下面的一个实现类而已
		c.add("张三");
		c.add("李四");
		c.add("王五");
		
		//c.remove("张三");//删除一个
       // System.out.println(c);//[李四,王五]
        
		Collection c3 = new ArrayList();//ArrayList是Collection下面的一个实现类而已
		c3.add("张三");
		c3.add("杨洪强");
		
		c.removeAll(c3);
		System.out.println(c);//[李四,王五]

(6)clear():清空所有
(7)retainAll(Collection<?> c) :保留交集 this = this ∩ c

Collection c = new ArrayList();//ArrayList是Collection下面的一个实现类而已
		c.add("张三");
		c.add("李四");
		c.add("王五");
		
		Collection c2 = new ArrayList();//ArrayList是Collection下面的一个实现类而已
		c2.add("张三");
		c2.add("杨洪强");
		c.retainAll(c2);
		System.out.println(c);//[张三]

(8)Object[] toArray() :把集合中的元素用一个数组返回

Collection c = new ArrayList();//ArrayList是Collection下面的一个实现类而已
		c.add("张三");
		c.add("李四");
		c.add("王五");
		
		Object[] all = c.toArray();
		System.out.println(Arrays.toString(all));//[张三,李四,王五]

Collection系列的3种集合遍历

(1)Object[] toArray():先返回数组,然后遍历数组
(2)迭代器设计模式, 每一个Collection系列的集合,内部都自带一个迭代器。
       java.util.Iterator:它是所有迭代器的标准接口。这个接口的实现类在每一种集合类中,例如:ArrayList内部有一个内部类实现了Iterator接口。
这里声明为内部类有两个原因:
          (1)每一种集合的内部实现(物理结构不同),意味着对迭代器(的实现是不同的,每一种集合都要单独定制迭代器
          (2)内部类可以直接访问外部类的私有的属性,成员,迭代器就可以直接访问集合的私有的元素。

判断是否还有下一个元素:hasNext()
访问它的下一个元素:next()
删除某个元素:remove()

Collection c = new ArrayList();//ArrayList是Collection下面的一个实现类而已
		c.add("张三");
		c.add("李四");
		c.add("王五");
				
		//返回这个集合自带的迭代器对象
		//从头挨个访问
		Iterator iterator = c.iterator();
		while(iterator.hasNext()){
			String obj = (String) iterator.next();
			//移除姓“王”
			if(obj.startsWith("王")){
				iterator.remove();
			}
		}		
		System.out.println(c);//张三  李四
		               //直接remove得把内容写全,灵活性不高

(3)foreach:增强for循环
foreach循环可以用于遍历数组、Collection系列的集合等容器。
语法结构:
for(元素的类型 元素临时名称 : 数组和集合名) {    }

Collection c = new ArrayList();//ArrayList是Collection下面的一个实现类而已
		c.add("张三");
		c.add("李四");
		c.add("王五");
		
		//Object:元素的数据类型
		//obj:临时的元素名称
		//c:要遍历的集合的名称
		for (Object obj : c) {
			System.out.println(obj);
		}

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

        stringArrayList.add("你好");
        stringArrayList.add("再见");
        stringArrayList.add("吃了吗你");
        for (Object obj :
                stringArrayList) {
            System.out.print(obj.toString()+" ");//你好 再见 吃了吗你
        }
        for (String str :
                stringArrayList) {
            System.out.print(str+" ");//你好 再见 吃了吗你
        }

   //遍历数组
  String[] arr = {"hello","world","java"};
		for (String string : arr) {
			System.out.println(string);
		}

什么样集合或容器类型可以使用foreach循环?
凡是实现了java.lang.Iterable接口(可迭代)的集合或容器都支持foreach循环 (implements Iterable)

如下:将上文自己定义的MyArrayList实现iterable接口:

public class MyArrayList implements Iterable{
private Object[] data;
	private int total;	
	public MyArrayList(){
		data = new Object[5];
	}	
... ... ... ...
	@Override//Iterable里面的抽象方法
	public Iterator iterator() {
	    //源码为return null;所以要重写才能使用
		return new MyItr();
	}
	
	private class MyItr implements Iterator{
		private int cursor;//游标

		@Override
		public boolean hasNext() {
			System.out.println("还有下一个");
			return cursor!=total;
		}

		@Override
		public Object next() {
			System.out.println("拿到下一个");
			return data[cursor++];
		}		
	}
	}

可见 foreach底层还是调用Iterator迭代器来遍历集合。

补:定义泛型的时候必须要将泛型写在前面,后面可以不写:

否则只能用object当做元素使用

java 如何循环遍历枚举值是否相等_java_03


java 如何循环遍历枚举值是否相等_System_04