当前位置:首页 > Java技术 > java set 长度

java set 长度

2022年08月06日 10:26:08Java技术8

本文主要是Java集合的概述和Set集合

1.Java集合概述

1)数组可以保存多个对象,但数组长度不可变,一旦在初始化数组时指定了数组长度,这个数组长度就是不可变的,如果需要保存数量变化的数据,数组就有点无能为力了;而且数组无法保存

具有映射关系的数据。为了保存数量不确定的数据,以及保存具有映射关系的数据,Java提供了集合类。集合类主要负责保存、盛装其他数据,因此集合类也被称为容器类。

2)Java集合类可用于存储数量不等的多个对象,并可以实现常用的数据结构,如栈、队列等。还可以用于保存具有映射关系的关联数组。Java集合大致可以分为Set、List、Map三种体系,

其中Set代表无序、不可重复的集合;List代表有序、重复的集合;Map则代表具有映射关系的集合。Queue体系集合代表一种队列集合实现。

3)集合类和数组不一样,数组元素既可以是基本类型的值,也可以是对象(实际上保存的是对象的引用变量);而集合类里只能保存对象(实际上保存的是对象的引用变量)。

4)Java集合类主要由两个接口派生出:Collection和Map。Set和List接口是Collection接口派生的两个子接口,他们分别代表了无序集合和有序集合;Queue是Java提供的队列实现。

Map实现类用于保存具有映射关系的数据。Map保存的每项数据都是key-value对,也就是由key和value两个值组成。Map里的key是不可重复的,key用于标识集合里的每项数据,如果需要查阅

Map中的数据时,总是根据Map的key来获取。

5)Collection接口是List、Set和Queue接口的父接口,该接口里定义的方法既可以用于操作Set集合、也可以用于操作List集合和Queue集合。

boolean add(Object o):该方法用于向集合里添加一个元素。

boolean addAll(Collection c):该方法把集合c里的所有元素添加到指定集合里。

void clear():清除集合里的所有元素,将集合长度变为0。

boolean contains(Object o):返回集合里是否包含指定元素。

boolean containsAll(Collection c):返回集合里是否包含集合c里的所有元素。

boolean isEmpty():返回集合是否为空。当集合长度为0时返回true,否则返回false。

Iterator iterator():返回一个Iterator对象,用于遍历集合里的元素。

boolean remove(Object o):删除集合中的指定元素o,当集合中包含了一个或多个元素o时,这些元素将被删除,该方法将返回true。

boolean removeAll(Collection c):将集合中删除集合c里包含的所有元素(相当于用调用该方法的集合减集合c),如果删除了一个或一个以上的元素,则该方法返回true。

boolean retainAll(Collection c):将集合中删除集合c里不包含的元素(相当于把调用该方法的集合变成该集合的集合c的交集),如果该操作改变了调用该方法的集合,则该方法返回true。

int size():该方法返回集合里元素的个数。

Object[] toArray():该方法把集合转换成一个数组,所有的集合元素变成对应的数组元素。

eg:

packagecn.it.lsl;importjava.util.ArrayList;importjava.util.Collection;importjava.util.HashSet;public classCollectionTest {public static voidmain(String[] args) {

Collection c= newArrayList();

c.add("小明");

c.add(6);

System.out.println("c集合的元素个数为:"+c.size());

c.remove(6);

System.out.println("c集合的元素个数为:"+c.size());

System.out.println("c集合是否包含\"小明\"字符串:"+c.contains("小明"));

c.add("JavaEE");

System.out.println("c集合的元素:"+c);

Collection books= newHashSet();

books.add("JavaEE");

books.add("Android");

System.out.println("c集合是否完全包含books集合?"+c.containsAll(books));

c.removeAll(books);

System.out.println("c集合的元素:"+c);

c.clear();

System.out.println("c集合的元素:"+c);//books集合里只剩下c集合里也包含的元素

books.retainAll(c);

System.out.println("books集合的元素:"+books);

}

}

6)Iterator接口遍历集合元素

Iterator接口也是Java集合框架的成员,主要用于遍历Collection集合中的元素,Iterator对象也被称为迭代器。

Iterator接口里定义了如下三个方法:

boolean hasNext():如果被迭代的集合元素还没有被遍历,则返回true。

Object next():返回集合里的下一个元素。

void remove():删除集合里上一次next方法返回的元素。

eg:

packagecn.it.lsl;importjava.util.Collection;importjava.util.HashSet;importjava.util.Iterator;public classIteratorTest {public static voidmain(String[] args) {

Collection books= newHashSet();

books.add("Java ee");

books.add("Java");

books.add("Andrroid");//获取books集合对应的迭代器

Iterator it =books.iterator();while(it.hasNext()){//it.next()方法返回的数据类型是Object类型

String book =(String)it.next();

System.out.println(book);if(book.equals("Java")){

it.remove();

}

book= "测试字符串";

}

System.out.println(books);

}

}

如果要创建Iterator对象,则必须有一个被迭代的集合。

packagecn.it.lsl;importjava.util.Collection;importjava.util.HashSet;importjava.util.Iterator;public classIteratorTest {public static voidmain(String[] args) {

Collection books= newHashSet();

books.add("Java ee");

books.add("Java");

books.add("Android");//获取books集合对应的迭代器

Iterator it =books.iterator();while(it.hasNext()){//it.next()方法返回的数据类型是Object类型

String book =(String)it.next();

System.out.println(book);if(book.equals("Android")){//it.remove();

books.remove(book);

}//book = "测试字符串";

}//System.out.println(books);

}

}

//当使用Iterator迭代访问Collection集合元素时,Colleection集合里的元素不能被改变,只有通过Iterator的remove方法删除上一次next方法返回集合元素才可以。

eg:

packagecn.it.lsl;importjava.util.Collection;importjava.util.HashSet;public classForeachTest {public static voidmain(String[] args) {

Collection books= newHashSet();

books.add("Java ee");

books.add("Java");

books.add("Android");for(Object obj : books){

String book=(String)obj;

System.out.println(book);if(book.equals("Android")){//以下代码会引发异常//books.remove(book);

}

}

System.out.println(books);

}

}

2.Set集合

Set集合与Collection基本上完全一样,它没有提供任何额外的方法。实际上Set就是Collection,只是行为略有不同。(Set不允许包含重复元素)。

Set集合不允许包含相同的元素,如果试图把两个相同的元素加入同一个Set集合中,则添加操作失败。

eg:

packagecn.it.lsl;importjava.util.HashSet;importjava.util.Set;public classSetTest {public static voidmain(String[] args) {

Set books= newHashSet();

books.add(new String("java"));boolean result = books.add(new String("java"));

System.out.println(result+ "-->" +books);

}

}

1)HashSet类

(1)HashSet是Set接口的实现。HashSet按Hash算法来存储集合中的元素,具有很好的存取和查找性能。

(2)HashSet不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也有可能发生变化。

(3)当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据该HashCode值决定该对象在HashSet中的存储位置。如果有两个元素

通过equals()方法比较返回true,但它们的hashCode()方法返回值不相等,HashSet将会把它们存储在不同的位置,依然可以添加成功。即,HashSet集合判断两个元素相等的标准是两个

对象通过equals()方法比较相等,并且两个对象的hashCode()方法返回值也相等。

eg:

packagecn.it.lsl;importjava.util.HashSet;classA{public booleanequals(Object obj){return true;

}

}classB{public inthashCode(){return 1;

}

}classC{public inthashCode(){return 2;

}public booleanequals(Object obj){return true;

}

}public classHashSetTest {public static voidmain(String[] args) {

HashSet books= newHashSet();

books.add(newA());

books.add(newA());

books.add(newB());

books.add(newB());

books.add(newC());

books.add(newC());

System.out.println(books);

}

}

注意问题:当把一个对象放入HashSet中时,如果需要重写该对象对应类的equals()方法,则也应该重写其hashCode()方法。其规则是:如果两个对象通过equals()方法比较返回true,则两个对象的hashCode值也应该相同。

重写hashCode()方法的基本规则:

1)在程序运行过程中,同一个对象多次调用hashCode()方法应该返回相同的值。

2)当两个对象通过equals()方法比较返回true时,这两个对象的hashCode()方法应返回相等的值。

3)对象中用作equals()方法比较标准的Field,都应该用来计算hashCode值。

如果向HashSet中添加一个可变对象后,后面程序修改了该可变对象的Field,则可能导致它与集合中的其他元素相同,这就可能导致HashSet中包含两个相同的对象。

eg:

packagecn.it.lsl;importjava.util.HashSet;importjava.util.Iterator;classR{intcount;public R(intcount){this.count =count;

}publicString toString(){return "R[count:" + count + "]";

}public booleanequals(Object obj){if(this ==obj)return true;if(obj != null && obj.getClass() == R.class){

R r=(R)obj;if(r.count == this.count){return true;

}

}return false;

}public inthashCode(){return this.count;

}

}public classHashSetTest2 {public static voidmain(String[] args) {

HashSet hs= newHashSet();

hs.add(new R(5));

hs.add(new R(-3));

hs.add(new R(9));

hs.add(new R(-2));

System.out.println(hs);

Iterator it=hs.iterator();

R first=(R)it.next();

first.count= -3;

System.out.println(hs);

hs.remove(new R(-3));

System.out.println(hs);

System.out.println("hs是否包含count为-3的R对象?" + hs.contains(new R(-3)));

System.out.println("hs是否包含count为5的R对象?" + hs.contains(new R(5)));

}

}

当向HashSet中添加可变对象时,必须十分小心。如果修改HashSet集合中的对象,有可能导致该对象与集合中的其他对象相等,从而导致HashSet无法准确访问该对象。

2)LinkedHashSet类

HashSet还有一个子类LinkedHashSet,LinkedHashSet集合也是根据元素的hashCode值来决定元素的存储位置,但它同时使用链表维护元素的次序,这样使得元素看起来是以插入的顺序保存的。也就是说,当遍历LinkedHashSet集合里的元素时,LinkedHashSet将会按元素的添加顺序来访问集合里的元素。

packagecn.it.lsl;importjava.util.LinkedHashSet;public classLinkedHashSetTest {public static voidmain(String[] args) {

LinkedHashSet books= newLinkedHashSet();

books.add("java");

books.add("Android");

System.out.println(books);

books.remove("java");

books.add("java");

System.out.println(books);

}

}

输出LinkedHashSet集合的元素时,元素的顺序总是与添加顺序一致。

虽然LinkedHashSet使用了链表记录集合元素的添加顺序,但LinkedHashSet依然是HashSet,因此它依然不允许集合元素重复。

3)TreeSet类

TreeSet是SortedSet接口的实现类,可以确保集合元素处于排序状态。

TreeSet中的几个方法:

Object first():返回集合中的第一个元素。

Object last():返回集合中的最后一个元素。

Object lower(Object e):返回集合中位于指定元素之前的元素(即小于指定元素的最大元素,参数元素不需要是TreeSet集合里的元素)。

Object higher(Object e):返回集合中位于指定元素之后的元素(即大于指定元素的最小元素,参数元素不需要是TreeSet集合里的元素)。

SortedSet subSet(formElement,toElement):返回次Set的子集合,范围从formElement(包含)到toElement(不包含)。

SortedSet headSet(toElement):返回此Set的子集,由小于toElement的元素组成。

SortedSet tailSet(fromElement):返回此Set的子集,由大于或等于fromElement的元素组成。

packagecn.it.lsl;importjava.util.TreeSet;public classTreeSetTree {public static voidmain(String[] args) {

TreeSet nums= newTreeSet();

nums.add(5);

nums.add(2);

nums.add(10);

nums.add(-9);

System.out.println(nums);

System.out.println(nums.first());

System.out.println(nums.last());

System.out.println(nums.headSet(4)); //不包含4

System.out.println(nums.tailSet(5)); //包含5

System.out.println(nums.subSet(-3, 4));

}

}

4)EnumSet类

EnumSet是一个专为枚举类设计的集合类,EnumSet中的所有元素都必须是指定枚举类型的枚举值。

EnumSet类没有暴露任何构造器来创建该类的实例,程序应该通过它提供的static方法来创建EnumSet对象。

static EnumSet allOf(Class elementType):创建一个包含指定枚举类里所有枚举值的EnumSet集合。

static EnumSet complementOf(EnumSet s):创建一个其元素类型与指定EnumSet里元素类型相同的EnumSet集合,新EnumSet集合包含原EnumSet集合所不包含的、此枚举类剩下的枚举值(

即新EnumSet集合和原EnumSet集合的集合元素加起来就是该枚举类的所有枚举值)。

static EnumSet copyOf(Collection c):使用一个普通集合来创建EnumSet集合。

static EnumSet copyOf(EnumSet s):创建一个与指定EnumSet具有相同元素类型、相同集合元素的EnumSet集合。

static EnumSet noneOf(Class elementType):创建一个元素类型为指定枚举类型的空EnumSet。

static EnumSet of(E first, E...rest):创建一个包含一个或多个枚举值的EnumSet集合,传入的多个枚举值必须属于同一个枚举类。

static EnumSet range(E from, E to):创建一个包含从from枚举值到to枚举值范围内所有枚举值的EnumSet集合。

eg:

packagecn.it.lsl;importjava.util.EnumSet;enumSeason{

SPRING,SUMMER,FAIL,WINTER

}public classEnumSetTest {public static voidmain(String[] args) {

EnumSet es1= EnumSet.allOf(Season.class);

System.out.println(es1);

EnumSet es2= EnumSet.noneOf(Season.class);

System.out.println(es2);

es2.add(Season.WINTER);

es2.add(Season.SPRING);

System.out.println(es2);

EnumSet es3=EnumSet.of(Season.SUMMER , Season.WINTER);

System.out.println(es3);

EnumSet es4=EnumSet.range(Season.SUMMER, Season.WINTER);

System.out.println(es4);

EnumSet es5=EnumSet.complementOf(es4);

System.out.println(es5);

}

}

复制另一个EnumSet集合中的所有元素来创建新的EnumSet集合,或者复制另一个Collection集合中的所有元素来创建新的EnumSet集合。当复制Collection集合中的所有元素来创建新的EnumSet集合时,要求Collection集合中的所有元素必须是同一个枚举类的枚举值。

packagecn.it.lsl;importjava.util.Collection;importjava.util.EnumSet;importjava.util.HashSet;public classEnumSetTest2 {public static voidmain(String[] args) {

Collection c= newHashSet();

c.clear();

c.add(Season.FAIL);

c.add(Season.SPRING);

EnumSet enumSet=EnumSet.copyOf(c);

System.out.println(enumSet);//c.add("java");//c.add("Android");//enumSet = EnumSet.copyOf(c);

}

}

当试图复制一个Collection集合里的元素来创建EnumSet集合时,必须保证Collection集合里的所有元素都是同一个枚举类的枚举值。

总结:

HashSet的性能总是比TreeSet好(特别是最常用的添加、查询元素等操作),因为TreeSet需要额外的红黑树算法来维护集合元素的次序。只有当需要一个保持排序的Set时,才应该使用TreeSet,否则都应该使用HashSet。

对于普通的插入、删除操作,LinkedHashSet比HashSet要略微慢一点,这是由维护链表所带来的额外开销造成的;不过,因为有了链表,遍历LinkedHashSet会更快。

EnumSet是所有Set实现类中性能最好的,但它只能保存同一个枚举类的枚举值作为集合元素。

作者:weixin_39962675
来源链接:https://blog.csdn.net/weixin_39962675/article/details/114111653

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。


本文链接:https://www.javaclub.cn/java/18244.html

标签: Java集合Java
分享给朋友:

“java set 长度” 的相关文章

两年前写的Java基础总结书

两年前写的Java基础总结书

想法衍生 两年前的我,突发奇想,把自己学的Java基础进行规范化的整理,因为自己的文档编辑能力有限,所以写的排版不是很好,参照图书排版的形式,将书籍进行整理,可以供学习Java基础的朋友参考,由于时间有限,可能也会有问题,请指出。下载地址在最后 截图如下:...

Java实现Email发送

一、前言最近将项目的登录密码从图形验证码改为了短信验证码,同时也将忘记密码时长度进行了修改,在修改时,想到了之前在一些国外的网站上,使用过邮箱接收验证码的情况,故想到何妨不自己尝试整合一下Java程序发送邮件信息呢,所以动手整合了Email的发送实例。二、Email发送协议想要在互联网上提供电子邮件...

Java中四种访问修饰符的区别

在java中共有4种访问级别,按访问权限由高到低为:public(公有的)、protected(受保护的)、友好的(没有任何访问权限关键字修饰)和private(私有的)。 类型 类内部 同一个包其...

Java 内存模型

Java 内存模型

📦 本文以及示例源码已归档在 javacore Java 内存模型(Java Memory Model),简称 JMM。 JVM 中试图定义一种 JMM 来屏蔽各种硬件和操作系统的内存访问差异,以实现让 Java 程序在各种平台下都能达到一致的内存访问效果。...

Java虚拟机1:什么是Java

Java虚拟机1:什么是Java

前言 让我们来看一下Java的广告词,来自http://www.java.com/zh_CN/about/: 97%的企业桌面运行Java 美国有89%的桌面(或计算机)运行Java 全球有900万Java开发人员 开发人员的头号选择...

Java 日志框架详解

Java 日志框架详解

1. JUL学习 JUL全称Java util Logging是java原生的日志框架,使用时不需要另外引用第三方类库,相对其他日志框 架使用方便,学习简单,能够在小型应用中灵活使用。 1.1 架构介绍 Loggers...

JDBC连接时所犯错误1.字符集设置不合适2.连接MySQL8.0社区版时时区不一致3..包名不能以Java.命名4.驱动被弃用

Microsoft JDBC Driver 的主页为:https://msdn.microsoft.com/en-us/data/aa937724.aspx 下载所需驱动 今天连接时报了四次错,记录下来 1.java.sql.SQLException:...

Java实现素数的判断

素数的定义只能被1和它本身整除,不包括1 例 2.3.5.7.11.13 实现代码 Scanner in=new Scanner(System.in); int n ; n=in.nextInt(); for(int n1=2;n1&l...

java之整数的分解可以理解为倒序输出

Scanner in=new Scanner(System.in); int number ; number=in.nextInt(); int result=0; do{ int diget=number%10;...

java数数字及while和do while 的使用,以及程序的调试与验证

while的条件是在进入循环体之前判断的,执行完一轮循环之后,会再回到循环开始的地方再次判断条件,而不会在循环体中随时判断条件 1.while语句是当条件满足时不断的执行循环体内语句。 2.会提前判断是否满足条件,所以有可能一次也没有执行。 3.条件成立...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。