一.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); } }