欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > > 文章正文

java进阶(三):反射(3)——数组的反射与集合的运用(ArrayList、HashSet),arraylisthashset

来源: javaer 分享于  点击 43674 次 点评:147

java进阶(三):反射(3)——数组的反射与集合的运用(ArrayList、HashSet),arraylisthashset


一、数组的反射

1、简单的数组反射:

1)同样类型切且具有相同维度的数组拥有同一份字节码

	/*
		 * 5- 数组的的反射
		 */
		int[] a1 = new int[3]; 
		int[] a2 = new int[4]; 
		int[][] a3 = new int[2][3]; 		
		String[] a4 = new String[3];
		
		System.out.println(a1 == a2);//false
		
		//同样类型切且具有相同维度的数组拥有同一份字节码
		System.out.println(a1.getClass() == a2.getClass());//true
2)getName()和getSuperclass()方法

		
		System.out.println(a1.getClass().getName());//[I : [-表示数组,I-整数,具体见文档
		System.out.println(a4.getClass().getName());//[Ljava.lang.String;
		
		//得到父类getSuperclass(),显示其父类的名字
		System.out.println(a1.getClass().getSuperclass().getName());//java.lang.Object
		System.out.println(a4.getClass().getSuperclass().getName());//java.lang.Object

2、Arrays和Array类的使用。

1)java.util.Arrays类:对数组操作的类,封装了大量静态方法操作数组。

例如:A、给数组赋值:通过fill方法;

   B、对数组排序:通过sort方法,按升序;

   C、比较数组:通过equals方法比较数组中元素值是否相等;

   D、查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作。

		int[] b1 = {9,6,3};
		String[] b2 = {"Z","Y","A"};
		String [] c = new String[3];
		
		//打印数组
		System.out.println(Arrays.asList(b1));//看不到值,原因是int不属于Object [[I@14318bb]
		System.out.println(Arrays.asList(b2));//可以看到打印的值 [Z, Y, A]
		
		//给数组赋值
		Arrays.fill(c, "4");
		System.out.println("查看数据C--"+Arrays.asList(c));//查看数据C--[4, 4, 4]
		
		//对数组排序:通过sort方法,按升序
		Arrays.sort(b2);
		System.out.println("排序后的数组b2--"+Arrays.asList(b2));//排序后的数组b2--[A, Y, Z]

2)java.lang.reflect.Array类:可以得到反射数组的类型,对反射数组进行赋值等操作。

        int[] temp={1,2,3,4,5};
        Class<?>demo = temp.getClass().getComponentType();
        System.out.println("数组类型: "+demo.getName());
        System.out.println("数组长度  "+Array.getLength(temp));
        System.out.println("数组的第一个元素: "+Array.get(temp, 0));
        Array.set(temp, 0, 100);
        System.out.println("修改之后数组第一个元素为: "+Array.get(temp, 0));
【输出】

数组类型: int
数组长度  5
数组的第一个元素: 1
修改之后数组第一个元素为: 1


3、综合运用:

/**
	 * 方法:传一个object,打印出来,数组就遍历
	 * @param obj
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 */
	private  static void printObject(Object obj) throws InstantiationException, IllegalAccessException{
		Class clazz = obj.getClass();
		if(clazz.isArray()) {//判断数组
			
			int len = Array.getLength(obj);//得到数组的长度
			for (int i = 0; i < len; i++) {
				System.out.print(Array.get(obj, i));
			}
			System.out.println();
			for(int i = 0; i < len; i++){
				Array.set(obj, i, 99);//赋值
				System.out.print(Array.get(obj, i));

			}
		}else {
			System.out.println();
			System.out.println(obj);
			
		}
	}
	
}
        int[] temp={1,2,3,4,5};		
        printObject(temp);//调用
        printObject("khjkhj");//调用
【输出】

12345
9999999999
khjkhj

二、ArrayList_HashSet的比较及Hashcode分析。

1、先定义一个实体,暂时没有重写父类的equals()和hashCode()方法。

package com.onhance.reflection;

/**
 * 
 * @title 反射用到的实例
 * @description
 * @author SAM-SHO
 * 
 * @Date 2014-6-29
 */
public class ReflectPoint {



	private int x;
	public int y;
	
	public String str1 = "ball";
	public String str2 = "basketball";
	public String str3 = "SAM SHO";
	
	
	public ReflectPoint(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
	
	

	@Override
	public String toString() {
		return "ReflectPoint [str1=" + str1 + ", str2=" + str2 + ", str3="
				+ str3 + "]";
	}


}

2、分别定义四个ReflectPoint对象,然后增加equals()hashCode()方法

		//1-先定义对象
		ReflectPoint pt1 = new ReflectPoint(3, 3);
		ReflectPoint pt2 = new ReflectPoint(5, 5);
		ReflectPoint pt3 = new ReflectPoint(7, 7);		
		ReflectPoint pt4 = new ReflectPoint(7, 7);
		
		//1-2比较pt3和pt4的关系
		//在ReflectPoint类重写hashcode与equals方法前为 : false,重写后,为true;
		System.out.println(pt3.equals(pt4));
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + x;//x、y参与哈希算法
		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;
		ReflectPoint other = (ReflectPoint) obj;
		if (x != other.x)
			return false;
		if (y != other.y)
			return false;
		return true;
	}

清楚的看到:pt3和pt4比较在前后发生的变化。

3、把实例分别放入ArrayList和HashSet容器,观察容器的大小。

//2-1 ArrayList集合
		//不管ReflectPoint有没有重写hashcode与equals方法,不管pt1-pt4之间的关系,长度适中为5
		//因为ArrayList有顺序,可以重复
		Collection <Object> list = new ArrayList<Object>();
		list.add(pt1);
		list.add(pt2);
		list.add(pt3);
		list.add(pt4);
		list.add(pt1);
		System.out.println("ArrayList的长度 : "+list.size());//显示长度为5
		
		//2-2 HashSet集合
		// 首先pt1只能放一个。
		// 没有重写hashcode和equesl方法时,pt3和pt4不 equals,即指向的不是同一个对象。所以都能放进去,长度为4
		// 重写hashcode和equesl方法后,pt3和pt4指向同一个对象,放不进去,长度为3.
		// 因为HashSet没有有顺序,不可以重复
		Collection <Object> set = new HashSet<Object>();
		set.add(pt1);
		set.add(pt2);
		set.add(pt3);
		set.add(pt4);   //pt3 equals pt4 重复,没有重写hashcode和equesl方法,就可以放进去)
		set.add(pt1);  //重复,放不进去,只能放一个pt1
		System.out.println("HashSet的长度 : "+set.size());//3个、4个

4、这边对哈希算法作简单介绍:

1)、哈希算法提高从集合中查找元素的效率,将集合分成若干个区域每个对象可以计算出一个哈希码,可以将哈希码分组,每组分别对应某个存储区域,根据一个对象的哈希码就可以确定该对象应该存储在哪个区域。

2)、HashSet底层用的也是数组。当向数组中利用add(Object o)添加对象的时候,系统先找对象的hashCode。
int hc=o.hashCode(); 返回的hashCode为整数值:Int I=hc%n;(n为数组的长度),取得余数后,利用余数向数组中相应的位置添加数据,以n为6为例,如果I=0则放在数组a[0]位置,如果I=1,则放在数组a[1]位置。如果equals()返回的值为true,则说明数据重复。如果equals()返回的值为false,则再找其他的位置进行比较。这样的机制就导致两个相同的对象有可能重复地添加到数组中,因为他们的hashCode不同。如果我们能够使两个相同的对象具有相同hashcode,才能在equals()返回为真。


5、当一个对象被存进集合中,不要去修改这个对象参加hash算法的属性,不然会破坏哈希算法。导致存进去的对象与修改后的对象具有不同的哈希值。这样最直接的问题就是,集合中的那个对象无法删除(当然有其他办法处理),造成内存泄露。

在上例中,x/y参与了哈希算法,现在改变y的值,看一下结果:

		//可以取走,结果长度为2
		set.remove(pt1);//可以取走
		System.out.println("HashSet的长度 : "+set.size());//2个
		
		//不可取走,结果为3
		pt1.y = 99;//y用于hashcode方法的计算,修改值以后,取不走:会导致内存泄露
		set.remove(pt1);//取不走
		System.out.println("HashSet的长度 : "+set.size());//3个
		
		set.clear();//我们可以清除
		System.out.println("HashSet的长度 : "+set.size());//0个

备注(写给自己):以后我会继续整理java中集合的内容。包括数据结构的内容和thinking in java中的内容。





相关文章

    暂无相关文章

用户点评