set,hashset及HashSet存储自定义对象保证元素唯一性的解析,还有eclipse批量替换查询


接口 Set<E>

	类型参数:
	E - 此 set 所维护元素的类型
  所有超级接口: 
Collection<E>, Iterable<E> 
  所有已知子接口: 
NavigableSet<E>, SortedSet<E> 
  所有已知实现类: 
AbstractSet, ConcurrentSkipListSet, CopyOnWriteArraySet, EnumSet, HashSet, JobStateReasons, LinkedHashSet, TreeSet 
  public interface Set<E> extends Collection<E>
  一个不包含重复元素的 collection。
更正式地说,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null 元素
Set集合,无索引,不可以重复,无序(存取不一致)


类 HashSet<E>

public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, Serializable
	此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。
它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。


public class a {

	public static void main(String[] args) {
		HashSet<String> hs = new HashSet<>();//创建HashSet对象
		boolean b1 = hs.add("a");//true
		boolean b2 = hs.add("a");//当向set集合中存储重复元素的时候返回为false
		hs.add("b");
		hs.add("c");
		hs.add("d");
		System.out.println(hs);	//HashSet的继承体系中有重写toString方法
		System.out.println(b1);
		System.out.println(b2);
		for (String string : hs) {//只要能用迭代器迭代的,就可以使用增强for循环遍历
			System.out.println(string);
		}
		
		
		HashSet<Student> hs1 = new HashSet<>();
		hs1.add(new Student("张三", 23));
		hs1.add(new Student("张三", 23));
		hs1.add(new Student("李四", 24));
		hs1.add(new Student("李四", 24));
		hs1.add(new Student("李四", 24));
		hs1.add(new Student("李四", 24));
		
		System.out.println(hs1.size());//6
		System.out.println(hs1);
		
		//其实在开发中,不用这么做,在student类中alt+shift+o+s自动生成hashcode and equals方法
		
	}

}

HashSet存储自定义对象不能保证元素唯一性
 	虽然我重写了student类中的equals方法

原因
 每一个自定义对象的hashcode值都不一样,所以他认为每个对象都是不同的,
 也就不会调用student类中的equals方法

 因此,我还需要重写他的hashcode方法
return 10;即Student每个对象的hashcode值都是10;
return 10;即Student每个对象的hashcode值都是10;
解释
		 * 在当我存储下一个对象时,由于他们的hashcode值都一样,就会自动调用equals方法
		 * 因为我重写了equals方法,当此对象与原对象相等时,就不会存储
		 * 如果不相等,就会把新对象堆在原对象上面
		 * 
		 * 接下来每次比较的时候,都会先和堆在最上面的对象比较

当调用add方法时就会调用hashcode方法,若hashcode相同又会调用equals方法
但我们不必每次都调用equals方法
使hashcode返回对象的属性,当属性不同的就不必在相同的位置存储,就减少equals方法的调用
这样就提高了程序的运行效率
String类重写了hashcode方法,可以借用此方法

其实在开发中,不用这么做,在student类中alt+shift+o+s自动生成hashcode and equals方法

重写后的这两个方法

/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;//
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	/*
	 * 为什么是31?
	 * 1:31是一个质数,质数是能被1和自己本身整除的数
	 * 2:31这个数既不大也不小
	 * 3:31这个数好算,2的五次方-1,2向左移动5位
	 */
	
	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	
	//健壮性判断
	@Override
	public boolean equals(Object obj) {
		if (this == obj)	//调用的对象和传入的对象是同一个对象
			return true;	//直接返回true
		if (obj == null)	//传入的对象为null
			return false;	//返回false
		if (getClass() != obj.getClass())//判断两个对象对应的字节码文件是否是同一个字节码
			return false;		//如果不是直接返回false
		Student other = (Student) obj;	//向下转型
		if (age != other.age)		//调用对象的年龄不等于传入对象的年龄
			return false;		//返回false
		if (name == null) {		//调用对象的姓名为null
			if (other.name != null)	//传入对象的姓名不为null
				return false;	//返回false
		} else if (!name.equals(other.name))//调用对象的姓名不等于传入对象的姓名
			return false;		//返回false
		return true;			//返回true
	}

下面是完整的student类

package bean;

public class Student {
	
	String name;
	int age;
	
	public Student() {
		super();
		
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	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;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
	/*@Override
	//alt+shift+o+s重写方法
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		System.out.println("执行了吗");
		Student s = (Student)obj;
		return this.name.equals(s.name) && this.age == s.age;
	}
	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		//return 10;
		return (name+age).hashCode();
	}*/
	
	
	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;//
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	/*
	 * 为什么是31?
	 * 1:31是一个质数,质数是能被1和自己本身整除的数
	 * 2:31这个数既不大也不小
	 * 3:31这个数好算,2的五次方-1,2向左移动5位
	 */
	
	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	
	//健壮性判断
	@Override
	public boolean equals(Object obj) {
		if (this == obj)	//调用的对象和传入的对象是同一个对象
			return true;	//直接返回true
		if (obj == null)	//传入的对象为null
			return false;	//返回false
		if (getClass() != obj.getClass())//判断两个对象对应的字节码文件是否是同一个字节码
			return false;		//如果不是直接返回false
		Student other = (Student) obj;	//向下转型
		if (age != other.age)		//调用对象的年龄不等于传入对象的年龄
			return false;		//返回false
		if (name == null) {		//调用对象的姓名为null
			if (other.name != null)	//传入对象的姓名不为null
				return false;	//返回false
		} else if (!name.equals(other.name))//调用对象的姓名不等于传入对象的姓名
			return false;		//返回false
		return true;			//返回true
	}
	
}

总结

HashSet如何保证元素唯一性的原理
* 1.HashSet原理
	* 我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降低了使用equals()方法的次数
	* 当HashSet调用add()方法存储对象的时候, 先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象
		* 如果没有哈希值相同的对象就直接存入集合
		* 如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存
* 2.将自定义类的对象存入HashSet去重复
	* 类中必须重写hashCode()和equals()方法
	* hashCode(): 属性相同的对象返回值必须相同, 属性不同的返回值尽量不同(提高效率)
	* equals(): 属性相同返回true, 属性不同返回false,返回false的时候存储

 

做这个的过程中还遇到一个问题,就是在eclipse中如何查找、批量替换

 eclipse批量查询替换
  1. ctrl+ H 打开 eclipse 的 search 面板或菜单Search ->Search( File也可以)
  2.选择 File Search 的tab
  3.在 Containing text 输入框中 输入你要替换(查找)的
  4.点击Search查看搜索结果,看看是否和预期一致
  5,选中你需要替换的工程或文件右键单击
  	Replace Selected 是只替换当前选中节点下的所有单词
	Replace All 是替换搜索结果中所有的单词
注意:也可以用正则表达式替换,前提是选中 Regular expression 复选框




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值