JAVA的HashCode和怎么加载文件

本文深入探讨了Java中hashCode与equals方法的重要性和实现原理。通过具体示例解释了如何正确重写这两个方法来确保对象在HashSet等集合中的唯一性,并讨论了哈希算法在对象存储与检索中的应用。
package reflect;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Properties;

public class HashCodeTest {
	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception{
		Collection c = new ArrayList();
		Collection c2 = new HashSet();
		Point p1 =new Point(3,5);
		Point p2 =new Point(1,5);
		Point p3 =new Point(2,5);
		Point p4 =new Point(3,5);
		c.add(p1);
		c.add(p2);
		c.add(p3);
		c.add(p4);
		c.add(p1);
		System.out.println(c.size());//5
		
		c2.add(p1);
		c2.add(p2);
		c2.add(p3);
		c2.add(p4);
		c2.add(p1);
		System.out.println(c2.size());//4
		/*
		 * 问题:怎么让c2的size为3,让p1 p4为同一添加对象?
		 * HashSet添加时判断判断是否相同的元素的依据是根据hashCode的值,hashCode是根据内存地址换算出来的,如想让p1,p4在HashSet为同一元素,只要重写hashCode方法和equal方法即可,
		 * 只重写hashCode或equal都不可以,
		 * 
		 */
		/*
		 * 任意打印几个对象的hashCode值,问题:hashCode值有什么用?
		 * 如果有100W个元素,要判断某个元素在不在这100W个元素中,传统方式就是一个一个的比较,效率很低下,hashCode的方式就是把集合分成若干区域,集合中的元素每个计算出个哈希码,然后把根据算法算出它的组,这个组就表示它的存储区域,这个对象就存在这个存储区域中,如果要找某个元素就直接在该区域中查找,大大提高了效率。
		 * HashSet等带Hash的集合基本都是按hashCode方式存储的,当在HashSet中查找某个元素时,先调用Object的hashCode返回一个哈希码,根据该哈希码判断相应存储区域,最后在用区域中的每个元素的equals方法和该元素比较,相同就返回。带有Hash的集合都带有很好的对象检索性能,
		 * 所以如果你想让两个对象的equals相等的话,那也要让这两个对象的hashCode也相等。
		 */
		System.out.println(c2.hashCode());
		System.out.println(c.hashCode());
		System.out.println(p1.hashCode());
		/*
		 * (1)只有类的实例对象要被采用哈希算法进行存储和检索的时候,这个类才需要按要求覆盖hashCode方法。
		 * (2)一般一个类的两个实例对象如果用equals比较相等,那么它们的hashCode必定相等,如果它们的hashCode相等,但不一定equal相等。如"BB"和“Aa”equals不等,但hashCode是相等的。
		 * (3)所以通常要求hashCode和equal一同被覆盖。
		 * (4)当对象存到HashSet后,就不能修改这个对象中参与计算hashCode值的字段了,否则,对象最初存在HashSet的哈希值和修改后的哈希值就不同了,造成的后果是很严重的,只要是与哈希算法相关的基本结果都不准确了,如果用contains方法可能失灵,remove()方法会失效,会造成内存泄露。如:
		 */
		p1.y=7;
		c2.remove(p1);//这句失效,存进去之后修改了参与hashCode计算的y,导致前后hashCode值不同,删除不了,如果List等则可正常删除,因为与HashCode无关。
		System.out.println(c2.size());
		/*
		 * 该删除的没删除的,一直在占着内存,就会造成内存泄漏。
		 */
		/*
		 * 问题:java中有没有内存泄露?举例说明。
		 */
		
		/*
		 * 动态加载:
		 */
		//Properties扩展自HashTable,把HashTable作用进行了增强,具体使用见源码API
		Properties pros = new Properties();
		//1.相对路径
		//FileInputStream fis = new FileInputStream("config.properties");//加载1,直接在根目录下加载,这种方式基本不用
		//InputStream fis = HashCodeTest.class.getClassLoader().getResourceAsStream("config/config.properties");//加载2,采用类加载器方式加载,相对目录。
		//InputStream fis = HashCodeTest.class.getResourceAsStream("/config/config.properties");//加载3,前面用/开头,表示直接在根目录下开始找。
		//2.绝对路径
		System.out.println(HashCodeTest.class.getResource(".").getPath());
		System.out.println(HashCodeTest.class.getClassLoader().getResource(""));
		System.out.println(HashCodeTest.class.getClassLoader().getSystemResource("."));
		String path = HashCodeTest.class.getResource(".").getPath();
		path = path.substring(0,path.indexOf("aa"))+"aa";
		System.out.println(path);
		FileInputStream fis = new FileInputStream(path+"\\config\\config.properties");//加载1,直接在根目录下加载,这种方式基本不用
		
		pros.load(fis);
		fis.close();
		String className = (String)pros.get("className");
		Collection col = (Collection)Class.forName(className).newInstance();
		col.add(p1);
		col.add(p2);
		col.add(p3);
		col.add(p4);
		col.add(p1);
		System.out.println(col.size());
		
	}

}
class Point{
	public int x;
	public int y;
	public Point(int x,int y){
		this.x=x;
		this.y=y;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + x;
		result = prime * result + y;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Point other = (Point) obj;
		if (x != other.x)
			return false;
		if (y != other.y)
			return false;
		return true;
	}
	
}

转载于:https://my.oschina.net/wrean/blog/167348

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值