JAVA集合Set,List,Queue,Map(一)

一、Java集合概述

  • 大致分为Set,List,Queue,Map四种体系。 Set代表无序的、不可重复的集合;List代表有序的、重复的集合,有点类似于List;
    Map代表具有映射关系的集合;Queue代表一种队列集合实现。
  • 集合类也被称为容器类,所有的集合类都位于java.util包下。
  • 集合和数组不一样,数组元素可以时基本类型的值,也可以是对象(实际上是对象的引用变量);而集合中只能保存对象(实际上是保存对象的引用变量)。
  • Java的集合类主要由两个接口派生而出:Collection(采集,聚集)和Map(映射,地图),Collection和Map是Java集合框架的根接口,这两个接口又包含了一些子接口或实现类。
  • 下图显示了Colleaction体系中的集合,在这里插入图片描述
  • 下图显示了Map体系的继承树,所有的Map实现类用于保存具有映射关系的数据。key-value对,key不可重复

在这里插入图片描述

  • 可以把Java所有集合分成三大类,Set,List,Map Set:类似于一个罐子,元素不能重复,无序的
    List:类似于一个数组,匀速可以重复,有序的 Map:类似于一个罐子,每项数据由两个值组成。
    访问List,用索引;访问Map,用key访问value;Set只能按元素本身来访问。
    常用的实现类:HashSet, TreeSet, ArrayList, ArrayQueue, LinkedList, HashMap, TreeMap

在这里插入图片描述
二、Collection和Iterator接口

  • 1.Collection接口是List,Set,Queue的父接口。该接口中定义的方法可以用在List,Set,Queue中。
  • 2.Lambda表达式遍历集合 Iterator中有一个方法forEach(), Iterator接口是Collection的父接口,因此Collection集合可以调用该方法。
    forEach()方法会自动将集合元素逐个地遍历集合元素。
Collection books = new HashSet();
books.add("Hello");
books.add("Bonjour");
books.forEach(obj -> System.out.println("迭代集合元素" + obj));

3.使用Iterator遍历集合元素
Collection,Map集合主要用来装其他对象,Iterator主要用来遍历Collection集合中地元素。Iterator对象被成为迭代器。
it.next()返回的数据类型是Object类型,因此需要强制类型转换
remove()删除上一次next()方法返回的集合元素
books.remove(book)会报错

public class IteratorTest
{
	public static void main(String[] args)
	{
		Iterator it = books.iterator();//获取books对应地迭代器
		while(it.hasNext())
		{//it.hasNext()方法返回的数据类型是Object类型,需要强制类型转换
			String book = (String)it.next();//先获取当前元素,再指向next();
			System.out.println(book);
			if(book.equals("Hello"))
				it.remove();
			book = "Test";//不改变集合元素本身
		}
		System.out.println(books);
	}
}

运行结果:
在这里插入图片描述

②Lambda表达式遍历Iterator


public class Num2Rmb {
	public static void main(String[] args)
	{
		Collection books = new HashSet();
		books.add("Hello");
		books.add("Bonjour");
		
		Iterator it = books.iterator();//获取books对应地迭代器
		it.forEachRemaining(obj->System.out.println("迭代集合元素:"+obj));
		//System.out.println(books);
	}
}

输出结果:
在这里插入图片描述
③使用foreach循环遍历集合元素

public class Num2Rmb {
	public static void main(String[] args)
	{
		Collection books = new HashSet();
		books.add("Hello");
		books.add("Bonjour");
		
		for(Object obj:books) {
			String book = (String)obj;
			System.out.println(book);
		}
	}
}

运行结果:
在这里插入图片描述
三、Set集合
Set集合:无序的,元素不能重复。下面介绍HashSet, TreeSet, EnumSet.
1.HashSet
基于Hash Map实现的。

①特点

  • 元素是无序的
  • HashSet不是同步的,如果多个线程或以上线程同时修改了HashSet,必须通过代码来保重其同步
  • 集合元素值可以是null

②hashCode

  • hash算法可以直接根据该元素的hashCode值计算出该元素的存储位置,快速定位元素。
  • HashSet中元素没有索引,当向其中添加元素时,HashSet会根据该元素的hashCode值计算它的存储位置,r如果两个元素通过equals()方法返回true,但它们的hashCode()返回值不同,HashSe会把它们存放在不同的位置。
  • HashSet中判断两个元素相等的标准:equals()==true && hashCode()返回值一样
  • HashSet中每个能存储元素的“槽位”称为“桶”,如果多个元素的hashCode()相同,equals()返回false,则需要在一个“桶”中存放多个元素,这回导致性能下降。
  • 注意:如果需要把某个类的对象保存在HashSet集合中,重写这个类的equals()方法和hasCode()方法时,应该尽量保证两个对象通过equals()方法比较返回true时,它们的hashCode()方法返回值也相等,保证与Set集合的规则不要冲突。

重写hashCode()的原则:

  • 程序运行过程中,同一个对象多次调用hashCode()方法应该返回相同的值
  • 两个对象通过equals()方法返回true时,它们通过hasCode()方法应该返后相等的值
  • 对象中用作equals()方法比较标准的实例变量,都应该用以计算hashCode值。
    注意:如果修改HashSet集合中的对象,有可能导致该对象与集合中的其他对象相等,从而导致HashSet无法准确访问该对象。

2.LinkedHashSet类

它也是根据hashCode()来决定元素的存储位置,集合中元素的顺序与添加顺序一致,不允许集合中有重复元素。使用链表记录集合元素的添加顺序。

3.TreeSet类

  • TreeSet类时SortedSet接口的实现类,TreeSet可以确保元素处于排序状态,根据大小排序。使用红黑树算法来维护集合元素的次序。
    TreeSet支持两种排序方法:自然排序、定制排序

(1)自然排序

  • TreeSet会调用compareTo(Object obj)方法来比较元素之间的大小关系,按升序排列。

  • Java定义了一个Comparable接口,该接口定义了compareTo()方法比较大小。

  • 如果将一个对象添加到TreeSet时,该对象的类必须实现Comparablbe()接口,否则引发运行时异常:ClassCastException。

  • 在实现compareTo(Object obj)方法时,需要把obj强制类型转换成相同类型,只有相同类的两个实例才会比较大小,新添加的元素必须跟集合中的其他元素类型一致,否则会报错:ClassCastException.

  • 当一个对象加入TreeSet集合中时,TreeSet调用该对象的compareTo(Object obj)方法与容器中的其他对象比较大小,然后根据红黑树结构找到它的存储位置。如果两个对象通过compareTo(Object obj)方法比较相等(返回值为0),新对象将无法添加到TreeSet集合中。

  • 重写一个类的equals()方法时,应保证该方法与compareTo(Object obj)方法有一致的结果:equals()方法返回true,compareTo()返回0.

  • 向TreeSet中添加一个可变对象后,并且后面的程序修改了该可变对象的实例对象,这将导致它与其他对象的大小顺序发生改变,但TreeSet不会调整他们的顺序,删除的时候也会出错。
    (2)定制排序

  • TreeSet默认排序:升序排序,如果想要定制排序:如降序排序,则可以通过Comparator()接口帮助,该接口包含一个int
    compare(T o1, T o2)方法,用于比较o1和o2的大小。
    定制排序时,需要在创建TreeSet对象时,提供一个Comparator对象与该TreeSet集合关联,由于Comparator是一个函数式接口(函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。函数式接口可以被隐式转换为 lambda 表达式。),因此可以用Lambda表达式代替comparator对象
    TreeSet ts = new TreeSet((o1,o2)->
    {
    M m1 = (M)o1;
    M m2 =(M)o2;
    return m1.age > m2.age ? -1 :m1.age<m2.age?1:0;
    }
    );
    TreeSet通过Comparator对象负责集合元素的排序规则。

4.EnumSet类
该集合中的元素有序,所有元素必须是指定枚举类型的枚举值。
不允许加入null元素。

5.各Set实现类的性能分析

  • EnumSet性能 > HashSet > TreeSet
  • EnumSet缺点:只能保存同一个枚举类的枚举值作为集合元素
  • HashSet比TreeSet性能好(特表是添加、查找等操作)的原因: 因为TreeSet需要额外的红黑树算法来维护集合元素的次序。
    只有当需要一个保持排序的Set时,才应该使用TreeSet,否则都用HashSet.
    HashSet的子类:LinkedHashSet,对于普通的插入、删除,LinkedHasSet慢,遍历时,LinkedHashSet快。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值