【CXY】JAVA基础 之 Set

本文详细介绍了Java中Set集合的不同实现类,包括HashSet、LinkedHashSet、TreeSet和EnumSet的特点及应用场景。探讨了它们如何处理重复数据、排序及性能差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述:

    1.Set不允许重复数据,判断重复标准:equals方法

    2.HashSet 

       1.无序(序号的序),允许存在null

       2.hashCode值决定它在HashSet中的位置,通过hashCode值算出存储位置

       3.判断重复标准:equals方法 和 hashCode方法 同时相等

             a.如果equals相同,hashCode不同,两个相同值的对象存在不同的位置(原因见第二点)

             b.如果hashCode相同,equals不同,采用链式结构将2个对象存在同一位置(桶的概念,bucket),这会导致性能下降

       4.两个概念初始容量 和 加载因子(hashSet尚未爆仓(只需达到初始容量*加载因子,即16*0.75),系统会动态扩大容量)

       5.没有实现线程同步 如果需要同步操作(多线程安全)请使用

Set s = Collections.synchronizedSet(new HashSet(...));

6.迭代过程中必须使用迭代器自身的remove方法删除数据,否则会出异常

    3.LinkedHashSet

       1.他是HashSet子类。

       2.它以链表的方式维护元素的次序,所以它会按照添加顺序访问集合中的对象。

       3.顺序遍历的时候性能比HashSet好,但是其他涉及到元素位置变化的操作性能就不如HashSet了。(数据结构知识)

       4.虽然它有一定的访问顺序,但是它和List还是有区别的,最明显的一点:它仍然不能有重复对象。

    4.TreeSet

       1.SortedSet接口的实现类,它保持了排序状态。

       2.方法:第一个、前一个、后一个、最后一个、范围截取、小于某元素、大于或者等于某元素

       3.采用红黑树的数据结构来存储数据

       4.支持2种排序方式:自然排序 和 定制排序

          1.自然排序

             a.调用Comparable接口的compareTo方法进行比较

             由于需要排序,进入TreeSet的对象需要是同一个类的实例,否则在比较的时候会出现类转化异常。

           2.定制排序

              实现Comparator接口(见例子)

       5.如果碰到不能排序的对象加入到TreeSet中 会出现异常(见例子)

    5.EnumSet

       1.性能相对不错的 枚举Set

       2.不多讲,有兴趣可以看看api

    6.HashSet、TreeSet、EnumSet都是线程不安全的


PS:

    1.Set不仅仅如此,这里只做基本的阐述,更加详细的请参见 JAVA API

    2.初学者挑能看懂的看吧,基础的操作其实还是比较简单的


package com.cxy.collection;

import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;

/**
 * @author cxy
 */
public class SetTest
{
	public static void main(String[] args)
	{
		Set s = new HashSet();
		s.add(null);
		s.add(new A());
		s.add(new A());
		//由于2个A对象的hashCode返回的都是1,并且equals方法返回的是true,所以这两个对象只能存在1个
		s.add(new B());
		s.add(new B());
		//B对象的equals方法返回的永远是false,所以这两个B对象都能留下
		s.add(new C());
		s.add(new C());
		//2个C对象hashCode返回的都是2,并且equals方法返回的是true,并且hashCode没有和以往对象相等的,所以留住1个C对象
		System.out.println(s); //通过打印结果可以看出 HashSet无序性。
		
		LinkedHashSet<String> lhs = new LinkedHashSet<String>();
		lhs.add("world");
		lhs.add("said");
		lhs.add("hello");
		System.out.println(lhs);  //按照加入顺序打印
		
		TreeSet ts=new TreeSet();
		ts.add(100);
		ts.add(64);
		ts.add(-100);
		ts.add(0);
		System.out.println(ts);  //发现打印出来的已然是有序状态
		System.out.println("第一个:"+ts.first()); 
		System.out.println("最后一个:"+ts.last()); 
		System.out.println("小于64的最大元素(64前面的):"+ts.lower(64));  
		System.out.println("大于0的最小元素(0后面的):"+ts.higher(0));  
		System.out.println("0~100之间的:"+ts.subSet(0, 100));  //半闭半开区间
		System.out.println("小于64的集合"+ts.headSet(64));
		System.out.println("大于或者等于0的集合"+ts.tailSet(0));
		
		try
		{
			TreeSet errorSet=new TreeSet();
			errorSet.add(new error());
			errorSet.add(new error());
		}catch(Exception e)
		{
			System.out.println("由于error类没有实现Comparable接口的compareTo方法,所以这里出现类型转换的异常");
		}
		
		try
		{
			TreeSet errorSet1=new TreeSet();
			errorSet1.add(123);
			errorSet1.add("asd");
		}catch(Exception e)
		{
			System.out.println("不同类实例的比较 会出类转换异常");
		}
		
		//一个定制排序的set
		TreeSet myStyleSet=new TreeSet(new Comparator()
		{
			@Override
			public int compare(Object o1, Object o2)
			{
				return 0;  //一个永远平等的集合~ 你懂的~
			}
			
		});  
	}
}

class A
{
	@Override
	public int hashCode()
	{
		return 1;
	}
	
	@Override
	public boolean equals(Object obj)
	{
		return true;
	}
}

class B
{
	@Override
	public int hashCode()
	{
		return 1;
	}
	
	@Override
	public boolean equals(Object obj)
	{
		return false;
	}
}

class C
{
	@Override
	public int hashCode()
	{
		return 2;
	}
	
	@Override
	public boolean equals(Object obj)
	{
		return true;
	}
}

//一个没有实现比较的类
class error
{
	
}

相关文章连接:

《JAVA基础 之 Collection》

《JAVA基础 之 List》

 

声明:

1.原创文章,转载请标明并加本文连接。

2.更详尽的API请参见  http://docs.oracle.com/javase/7/docs/api/

3.文章反映个人愚见,如有异议欢迎讨论指正 


### Java 中数据库数据映射到实体类 VO 的方法 在 Java 开发中,将数据库中的数据映射到实体类并进一步转化为 VO(值对象),是一种常见需求。以下是具体实现方式及其相关技术说明。 #### 使用 JPA 或 MyBatis 进行数据库查询并将结果映射至实体类 JPA 和 MyBatis 是两种常用的 ORM 工具,可以轻松完成从数据库表到 Java 实体类的映射操作。假设有一个 `NursingProject` 表,其对应的实体类如下: ```java @Entity @Table(name = "nursing_project") public class NursingProject { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private Double price; private String remark; // Getters and Setters } ``` 当通过 JPA 查询该表时,可以直接返回 `List<NursingProject>` 类型的结果集[^1]。 --- #### 将实体类转换为 VO 值对象 为了满足前端展示的需求,通常需要将上述实体类 `NursingProject` 转换为专门设计的 VO 对象。例如,创建一个名为 `NursingProjectVo` 的类: ```java public class NursingProjectVo { private String name; private Double price; private String remark; // Getters and Setters } ``` 此时可以通过手动编写转换逻辑或将工具引入项目来简化这一过程。 --- #### 手动编写的简单示例 如果仅涉及少量字段,则可采用简单的 getter/setter 方法进行转换: ```java public static List<NursingProjectVo> convertToVos(List<NursingProject> entities) { List<NursingProjectVo> vos = new ArrayList<>(); for (NursingProject entity : entities) { NursingProjectVo vo = new NursingProjectVo(); vo.setName(entity.getName()); vo.setPrice(entity.getPrice()); vo.setRemark(entity.getRemark()); vos.add(vo); } return vos; } ``` 这种方式虽然直观易懂,但在字段较多的情况下显得冗余且容易出错[^3]。 --- #### 利用 MapStruct 自动生成映射代码 MapStruct 可显著提升开发效率,尤其适用于复杂的对象间映射场景。首先,在 Maven 项目的依赖文件中加入以下配置: ```xml <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>1.5.3.Final</version> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.5.3.Final</version> <scope>provided</scope> </dependency> ``` 接着定义一个接口用于描述两者的映射关系: ```java @Mapper(componentModel = "spring") public interface NursingProjectMapper { NursingProjectMapper INSTANCE = Mappers.getMapper(NursingProjectMapper.class); NursingProjectVo toVo(NursingProject entity); List<NursingProjectVo> toVoList(List<NursingProject> entities); } ``` 运行构建工具后,MapStruct 会自动生成具体的实现类,并提供高效的映射功能[^2]。 调用此接口即可快速完成转换: ```java List<NursingProject> entities = nursingProjectRepository.findAll(); // 获取所有记录 List<NursingProjectVo> vos = NursingProjectMapper.INSTANCE.toVoList(entities); // 自动映射 ``` --- #### 总结 以上展示了如何利用传统方法与现代框架相结合的方式,高效地将数据库数据映射至实体类再转化成 VO 值对象的过程。无论是基础的手工编码还是借助像 MapStruct 这样的自动化工具,开发者都能找到适合自己的解决方案以优化工作流程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值