Java学习之Collection、List、Set

今天来总结一下这几天学习的关于java的集合框架的内容:

集合,某种程度而言是在数组的基础上发展而来,算的上是”数据容器”的高级版本。
首先看看集合和数组之间的异同吧!

我们存储大量的"对象引用",使用数组:
数组:
1。数组的长度不可变。(局限性)
2。数组只能存储同类型;

那么有没有什么类似于数组的容器,对于程序员来说,可以无限的存储任何的对象引用。也正是这样的需求,促使集合类的出现!
集合类:
1。集合类本质上就是一个容器,存储对象引用;
2。对于程序员来说,它似乎可以无限的存储任意数量的对象引用。(与数组的不同,也是我们使用集合的原因,用起来比较方便。)
3。集合只能存储引用类型的数据。(这里有一个注意点:我们在工作中会看到直接将一个基本数据类型存储到集合中,其实这是隐式的装箱操作,存储的仍然是引用)

数组和集合的共同点:
1。都是容器;
不同点:
1。数组是定长的。集合的长度可变的。
2。数组可以存储任何类型的数据;
集合只能存储引用类型;

集合有ArrayList、Vector、LinkList、HashSet、LinkedHashSet、TreeSet、HashMapTreeMap等多种实现。为了屏蔽实现差异,java提供了一个Collection接口和Map接口,规定必须实现一些公用的成员方法,比如add、remove、contains、isEmpty、size等等。
不管底层细节是如何实现,这些实现接口的子类至少拥有上面方法。

集合框架包含了两部分:一部分是接口,一部分是类

Collection主要结构图:

常见混淆处:

1。 在集合框架中,接口Map和Collection在层次结构上没有任何关系,它们是截然不同的,千万不要自以为Map接口也是继承自Collection接口哦。
2。 Collection、Lis、Set和Map都只是接口,不是具体的类(即不可直接实例化对象)实现。

Collection 接口:
Collection 层次结构 中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。JDK 不提供此接口的任何直接实现:它提供更具体的子接口(如 Set 和 List)实现。此接口通常用来传递 collection,并在需要最大普遍性的地方操作这些 collection。
所有通用的 Collection 实现类提供两个“标准”构造方法:一个是 void(无参数)构造方法,用于创建空 collection;另一个是带有 Collection 类型单参数的构造方法,用于创建一个具有与其参数相同元素新的 collection。实际上,后者允许用户复制任何 collection,以生成所需实现类型的一个等效 collection。 ----- 此段 摘自JAVA API 官方文档

如何遍历Collection中的每一个元素?
用该迭代器即可逐一访问Collection中每一个元素,collection实现类皆支持一个iterator()的方法,该方法实现遍历功能。

Iterator it = collection.iterator();  
while(it.hasNext()){  
    Object obj = it.next();  
}  

||- - List接口

List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(类似于数组下标)来访问list中的元素。和下面要提到的Set不同,List允许有相同的元素。
除了因继承自Collection接口具有Collection接口必备的iterator()方法外,list还提供一个listiterator()方法,返回一个Listiterator接口,和标准的iterator接口相比,还允许添加、删除、设定元素、还能向前或向后遍历。

实现List接口的常用类有以下:
||- - List 接口
||- -ArrayList类

||- - List 接口
||- -LinkedList类

LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的get、remove、insert方法在LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈,队列或者双向队列。

LinkedList:不保证线程安全,效率高。链表实现;
特有功能:
public void addFirst(E e)及addLast(E e)
public E getFirst()及getLast()
public E removeFirst()及public E removeLast()

||- - List 接口
||- -Vector类

Vector 类是基于数组实现的List 类,Vector 比较古老,被ArrayList 取代了。
虽然ArrayList 是线程不安全的,而Vector 是线程安全的,但是即使这样,也不推荐使用Vector,因为Collections 有方法可以得到线程安全的ArrayList 对象。

比较可总结出List三个子类的特点:
ArrayList: 底层 数组 实现。不保证线程安全,常用于单线程访问。速度较快。
Vector: 底层 数组 实现。线程安全的,可以多线程访问。速度较慢。
LinkedList: 底层 链表 实现。不保证线程安全。速度快。

并发修改异常产生的原因:
当我们通过Iterator遍历集合时,因为Iterator已经有了一份集合的拷贝,它将遍历这个集合,如果正在遍历时,通过"集合对象"去向集合中添加元素时,与Iterator的拷贝就不一致了,这时就产生一个:并发修改异常;

解决方法:
1.使用ListIterator遍历,可以通过ListIterator去添加元素:添加到当前元素的后面;
2.使用List遍历,使用List去添加:添加到集合的最后;

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

public class Demo {
	public static void main(String[] args) {
		List list = new ArrayList();
		list.add("aaa");
		list.add("bbb");
		list.add("ccc");
		
		/*
		 * 并发修改异常:
		 * Iterator it = list.iterator();
		   while(it.hasNext()){
			//正在使用迭代器遍历时,通过list去向集合中添加元素
			String str = (String)it.next();//java.util.ConcurrentModificationException
			if(str.equals("bbb")){
				list.add("eee");
			}
		}*/

		//解决方法一:使用ListIterator遍历集合,通过ListIterator去修改
		/*ListIterator listIt = list.listIterator();
		while(listIt.hasNext()){
			String str = (String)listIt.next();
			if(str.equals("bbb")){
				listIt.add("eee");
			}
		}
		System.out.println(list);*/

		//解决方法二:使用List遍历,使用List添加
		for(int i = 0;i < list.size();i++){
			String str = (String)list.get(i);
			if(str.equals("bbb")){
				list.add("eee");
			}
		}
		System.out.println(list);
		
	}
}

Set 接口:
虽然Set接口是无序(取出的顺序不同于存入的顺序)的,但不允许重复元素,即使是null值,也只能存唯一一个。
Set保证不重复的原理:
1.先调用集合中每个对象的hasCode()方法与参数的hasCode()方法的值进行比较,如果相同,继续判断equals()方法;否则,认为不同。
2.简单说就是两个对象的hasCode()返回值相同,并且两个对象的equals()方法返回true。则认为相同,禁止存储.

||- -Set接口
||- -HashSet类

||- -Set接口
||- -LinkedHashSet类

||- -Set接口
||- -TreeSet类

TreeSet 是SortedSet 接口唯一的实现,与HashSet 相比额外的方法如:
Comparator comparator(): 返回当前Set 使用的Comparator,若返回null,表示以自然顺序排序。

1.自然排序:
2.定制排序 (比较器):
TreeSet 的自然排序是根据元素的大小进行升序排序的,若想自己定制排序,比如降序排序,就
可以使用Comparator 接口;

我在基础测试阶段时涉及到的真题分析,使用了自定义比较器(即定制排序)的方式重写
声明类Student,包含3个成员变量:name、age、score,
创建5个对象装入TreeSet,按照成绩排序输出结果(考虑成绩相同的问题)。

分析:题目中要求排序,那么很自然会想到Tree结构,由于是按照单项比较,故TreeSet可满足要求;题目有强调考虑成绩相同情况,故可以根据年龄进行排序,分数相同但年龄小的可排在前面,更需要使用比较器进行比较,自己重写compare()方法,进行排序。

import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;


//定义学生Student类,包含成员属性 name、age、score
 class Student{
		private String name;
		private int age;
		private int score;
		
		public Student(String name, int age, int score) {
			super();
			this.name = name;
			this.age = age;
			this.score = score;
		}
		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 int getScore() {
			return score;
		}
		public void setScore(int score) {
			this.score = score;
		}
	
}

 
public class Test {
	
	public static void main(String[] args) {
		//使用比较器实例化一个TreeSet,并且重写其中的compare()方法
		//实例化TreeSet时,使用构造函数:TreeSet<>(Comparator com);
		TreeSet<Student> stuSet = new TreeSet<>(new Comparator<Object>(){

			public int compare( Object obj1,  Object obj2) {
				 //obj 转换为 Student
				 Student stu1 = (Student)obj1;
				 Student stu2 = (Student)obj2;
				 //比较分数,分数高的排名靠前
				 int Score = stu2.getScore() - stu1.getScore();
				 //当分数一致时,则比较年纪,年纪小的排名靠前
				 int Age = (Score == 0 ? stu1.getAge() - stu2.getAge(): Score);
				 return Age;
			}});
		
		//循环输入5个Student对象的成员信息
		for(int i = 1 ;i <= 5 ; i++){
			System.out.println("请输入第 "+ i +"名学员信息:");
			System.out.print("姓名:");
			String name = (new Scanner(System.in)).next();
			System.out.print("年龄:");
			int age = (new Scanner(System.in)).nextInt();
			System.out.print("分数:");
			int score = (new Scanner(System.in)).nextInt();
			
			//封装Student对象
		    Student stu = new Student(name,age,score);
		     
		    //将每一个输入的对象信息添加到stuSet集合中
		    stuSet.add(stu);
	   }		
		   System.out.println("\t姓名\t年龄\t分数");
		   //使用增强for遍历stuSet集合中的所有元素,并打印出排好顺序的集合元素
			for(Student stu : stuSet){
				System.out.println("\t"+ stu.getName() + "\t" + stu.getAge() + "\t" + stu.getScore());
		}
	}	
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值