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