Java复习之知识点整理(十一)---- ArrayList、LinkedList、Map、hashSet、hashcode、TreeSet

一.ArrayList 集合
--------------------------------------------
1.内部使用的是 object[] 作为数据底层结构
2.Capacity容量:当数组的size达到容量最大值的时候,会进行扩容复制,所以增删慢
3.size:表示数组中元素的个数,一般小于容量
4.采用index + offect机制:所以查询快
5.内容可重复,有序的
6.如果判断对象是否存在,使用的是equals方法,所以一般需要重写equals方法,但是跟hashcode没有关系,不必重写hashcode


二、LinkedList 链表
---------------------------------------------
1.内部使用的是链表结构作为底层接口,所以,增删快,但是查询慢
2.内容可重复,有序的
3.如果判断对象是否存在,使用的是equals方法,所以一般需要重写equals方法,但是跟hashcode没有关系,不必重写hashcode


三、Map
----------------------------------------------
1. K V 映射
2. 条目:Entry === <k v>
3. key具有唯一性

四、hashSet/hashMap
---------------------------------------------
1.元素唯一,不重复
2.hashMap 和 hashSet 没有本质的区别
3.对于hashMap存放元素是否相同的判断要经过以下步骤
①取得初始hash值:
通过自定义重写之后的hashCode()方法,取得要put进去对象的初始hash值
②计算新hash特征值:
newHash = (hash ^ (hash >>> 16)),计算新哈希值newHash
②确定桶号:
hashcode对桶的总数量n进行 hash& (n - 1)运算,判断该对象应该放入第几个桶(位运算之后,只能是0-->n-1)
④放入元素,查重:
确定好在哪个桶之后,首先判断桶里面是否是空的,如果为空,直接放入元素,如果不为空, 就看这个桶(里面是链表)里是否已经存在要放入的对象,这时就需要从链表的第一个开始往后对比对象是否存在
每次对比,都要经过两个阶段的比较:
a.比较对象的hashcode,如果不一致,认为对象不重复,直接放入链表队列;
b.如果hashcode一致,那么接下来进行 == 和 equals的判断,如果有一个相同,那么就认为是重复元素;
c.如果 == 和 equals都不一样,那么就是非重复元素,放入链表队列;
4.hash作为首要判断条件,不相同就是不重复;如果hash相同 , == 和 equals ,二者都不同,才是不重复
5.是否重复的判断条件: hashcode && ( == || equals)
6.hashSet的底层首先是桶的集合,每个桶内又是链表进行存储的,相当于集合中的元素是链表,大大的增加了查找的效率
7.兼具集合和链表的优势,检索和读写速度很很快

五、hashcode
-----------------------------------------------------------------------
1.object类的hashCode()方法,默认计算出的hashcode是内存地址值,如果不使用hashSet集合,一般不用重写此方法但是一旦是hashmap和hashSet集合,并且key是自定义类(非包装类,因为包装类已经帮我们写好了),那么key的自定义类一定要重写hashCode()和equals()方法。
2.hashcode一般作为hashSet集合和hashMap集合的特征值使用,用于快速查找元素的位置。

六、hash特征值:
-----------------------------------------------------------------------
1.概念:目的就是把对象所有的特征(姓名,年龄,血型,身高等),压缩到一个int数字上去,这个int数字就是特征值,压缩的过程就是特征值算法
2.hash怎么来的: hash = (key.hashCode() ^ (hashCode() <<< 16));
解释:①:int 是 4个字节,32位,无符号右移16位,表示将高位的2个字节移动到了低位
②:^ 异或运算,相同为0,不同位1,0和1的概率均为50%,而且达到了数据分散的作用
③:首先将hashCode右移16位,保证了高位的参与,其次原值与移动之后的值进行异或运算,将数组最大程度的等概率发散,将数据充分的打散。
3.hash是怎么进行桶定位的
hash & (n - 1) // n为桶的总数,一般为

七、TreeSet / TreeMap

--------------------------------------------------------

1.通过comparator.compareTo 或者 comparable.compare()方法来保证元素的唯一性。
2.内部的存储形式为二叉树形式
3.实现了对key的排序,但是排序规则需要你自定义
4.自定义类型的对比的两种实现方式:
①定义一个对比器DogCompartor,implements Comparator<Dog>,重写public int compare(Dog o1, Dog o2)方法
②自定义类直接实现Comparable接口, class Dog implements Comparable<Dog>,重写compare方法
5.二叉树的思想:
①首先定义跟节点,每个节点都有左右两个分支,当存放元素的时候,会先比较节点元素和待存入元素的大小(compare方法),如果相同,则重复,如果待放入元素大,则去查看右侧分支,小则查看左侧分支。
②重复①过程,直到没有节点元素可对比或者待放入元素重复为止。
③如果没有节点可对比了,那么带放入节点大于最后节点,就放入最后节点的右侧分支。如果小,就放入左侧分支。
④所以,二叉树的key是有排序的,默认从小到大排序

@Test
	public void tsTreeSet01()
	{
		Set<Integer> set = new TreeSet<Integer>();
		set.add(1);
		set.add(2);
		set.add(3);
		set.add(4);
		System.out.println(set.size());
	}

	@Test
	public void tsTreeSet02()
	{
		Set<Dog> set = new TreeSet<Dog>(/*new DogCompartor()*/);
		set.add(new Dog("dahuang1"));
		set.add(new Dog("dahuang2"));
		set.add(new Dog("dahuang3"));
		set.add(new Dog("dahuang4"));
		System.out.println(set.size());
	}
	
	@Test
	public void tsTreeMap01()
	{
		Map<Dog,String> map = new TreeMap<Dog,String>();	
		map.put(new Dog("dahuang1"), "111");
		map.put(new Dog("dahuang2"), "222");
		map.put(new Dog("dahuang3"), "333");
		map.put(new Dog("dahuang4"), "444");		
		System.out.println(map.size());	
	}

class Dog implements Comparable<Dog>
{
	public String name = "";

	public Dog(String name) {
		super();
		this.name = name;
	}

	@Override
	public int compareTo(Dog o) {
		
		if(o == null)
		{
			return 1;
		}
		return this.name.compareTo(o.name);
	}
}

//Dog 对比器
class DogCompartor implements Comparator<Dog>
{
	public int compare(Dog o1, Dog o2) {
		
		if(o1 == null)
		{
			if(o2 == null)
			{
				return 0;				
			}
			else
			{
				 return -1;
			}				
		}
			
		else
			if(o2 == null)
			{
				return -1;				
			}
			else
			{
				return o1.name.compareTo(o2.name);
			}				
	}	
}



八、实现链表,成环
---------------------------------------------------------------------------------------------

//链表成环
class MyLinkedList
{
	//集合大小
    public int size = 0;

    //第一个节点
    public Node first;

    //最后一个节点
    public Node last;
  
    //增加元素
    public void add(Object e) {
    	//取得原来的尾部节点
        Node l = last;
        //新建新的节点,并且新节点的尾部链接首节点(成环的关键)
        Node newNode = new Node(l, e, first);
        //赋值
        last = newNode;
        //如果尾部节点为空,说明是空链表
        if (l == null)
        {
        	first = newNode;
         	first.prev = last;
         	first.next = last;
         	last.prev = first;
         	last.next = first;
        }
           
        //如果不为空,那么将新建节点,链接到原来尾节点之后
        else
            l.next = newNode;
        
        size++;
    }
    
    //首节点
    public Object getFirstItem()
    {
    	return first.item;
    }
    
    //尾节点
    public Object getLastItem()
    {
    	return last.item;
    }
    
    //尾节点的下一个节点
    public Object getLastNextItem()
    {
    	return last.next.item;
    }
  
    //首节点的上一个节点
    public Object getFirstPrveItem()
    {
    	return first.prev.item;
    }
        
    //内部节点类
    private static class Node {
        
    	//存放object的item
        Object item;
    	//下一个节点
        Node next;
        //上一个节点
        Node prev;
        
        //节点的构造函数
        Node(Node prev, Object element, Node next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }
}

@Test
	public void tsMyList01()
	{
		MyLinkedList myList = new MyLinkedList();
		myList.add((Object) "1");
		myList.add((Object) "2");
		myList.add((Object) "3");
		myList.add((Object) "4");
		//System.out.println(myList.size);
		//System.out.println((String)myList.getFirstItem());
		//System.out.println((String)myList.getLastItem());
		System.out.println((String)myList.getFirstPrveItem());
		System.out.println((String)myList.getLastNextItem());
	}



九、自定义特征值int:Person{int height,int weight,int blood,int age}
-------------------------------------------------------------------------------------------
@Override
	public int hashCode() {
		
		int newBlood = blood & 0xff;
		int newAge = age & 0xff00;
		int newHeight = height & 0xff0000;
		int newWeight = weight & 0xff000000;
		
		return newBlood | newAge | newHeight | newWeight;
	}


十、使用位运算,将byte的范围转换成0-255
------------------------------------------------------------------------------------------
@Test
	public void tetsByteTo0_255()
	{
		System.out.println(byteTo0_255((byte)-128));
		System.out.println(byteTo0_255((byte) -1));
		System.out.println(byteTo0_255((byte) 0));
		System.out.println(byteTo0_255((byte) 127));
	}
	
	public int byteTo0_255(byte b)
	{
		if(b > 0)
		{
			return (b | 0x80);			
		}
		else 
		{
			return (b & 0x7f);
		}
	}





猜你喜欢

转载自blog.csdn.net/xcvbxv01/article/details/80884567
今日推荐