您的位置:首页 > 其它

黑马学习笔记--单例集合(Collection)

2017-04-02 22:55 375 查看

List

ArrayList数组实现的原理

数组实现的特点: 查询快,增删慢

- 原因:

- 查询快: 由于数组的索引支持,那么可以通过索引直接计算出元素的地址值,因此就可以直接通过元素的地址值获取到指定的元素

增删慢: 由于在添加元素的时候,实际上底层会先创建一个新数组(新数组的长度为原数组的长度+1),那么在添加新元素的时候,先需要对数组中原有的数据进行拷贝,其次在末尾进行添加新的元素因此,这样操作的效率的极低的(删除元素 刚好和添加的操作相反)

LinkedList链表实现的原理

链表结构: 查询慢,增删快

- 原因:

- 查询慢:由于不能直接找到元素的地址,需要上一个元素推导出下一个元素的地址,这种查询速度较慢

- 增删快:在添加的时候,只需要更改元素所记录的地址值即可

LinkedList的使用&数据结构

基本使用

LinkedList与ArrayList不同,LinkedList是方便添加删除的List。

实际开发中对一个集合元素的添加与删除经常涉及到首尾操作,所以该具体子类的特点在于提供了大量首尾操作。

public void addFirst(E e) 添加首个元素

public void addLast(E e) 添加最后元素

public E getFirst() 获取首个元素

public E getLast() 获取最后元素

“` JAVA

/*

LinkedList是方便添加删除的List。

提供了大量首尾操作

*

public void addFirst(E e) 添加首个元素

public void addLast(E e) 添加最后元素

public E getFirst() 获取首个元素

public E getLast() 获取最后元素

*/

public class Demo01LinkedList {

public static void main(String[] args) {

//创建集合对象
LinkedList<String> list = new LinkedList<String>();
//向集合中添加元素
list.add("Jack");
list.add("Rose");
list.add("Trump");
//获取元素
String name = list.get(1);
System.out.println(name);

//返回集合的迭代器
Iterator<String> itr = list.iterator();
while(itr.hasNext()) {
String thisName = itr.next();
System.out.println(thisName);
}
System.out.println("=======================");
//使用增强for循环
for (String thisName : list) {
System.out.println(thisName);
}

System.out.println("======================");
//做首尾的添加与删除动作
System.out.println(list);

list.addFirst("LiLei");
list.addLast("HanMeiMei");
System.out.println(list);

System.out.println(list.getFirst());
System.out.println(list.getLast());


}

}

### 数据结构

- 栈结构:容器先进后出规则
- 每种集合的特点不同(如更适合增删还是更适合查找),是因为底层的数据结构不同。
- 数据结构指的数据存储和组织方式.
- 数组结构:一块连续的存储区域
- 链表结构:每个元素指向下一个元素

``` JAVA
/*
* stack栈结构:先进后出
*
* LinkedList是支持栈结构的.
* 对应的方法
*      push压栈
*      pop弹栈
*      peek查询出即将要弹出的是哪个元素,检查有没有要弹出的元素
*
* java提供了一个专门用于栈结构的类,Stack
*/
public class Demo02stack {

public static void main(String[] args) {

//创建栈结构的集合
LinkedList<String> stack = new LinkedList<String>();

stack.push("Jack");
stack.push("Rose");
stack.push("Trump");

System.out.println(stack);

//获取一个元素,此时,由于是栈结构,所以获取的是最后压栈的元素
String popName = stack.pop();
System.out.println(popName);
//弹栈动作,集合中减少元素
System.out.println(stack);

String peekName = stack.peek();
System.out.println(peekName);
//peek查看元素不会减少元素
System.out.println(stack);
}

}

<div class="se-preview-section-delimiter"></div>


队列结构

容器先进先出的规则

/*
* queue队列结构:
*
* LinkedList是支持队列结构的
* 对应的方法
*      offer加入队列
*      poll离开队列
*      peek查询出即将要离开队列的是哪个元素,检查有没有要离开队列的元素
*/
public class Demo03queue {

public static void main(String[] args) {

//创建栈结构的集合
LinkedList<String> queue = new LinkedList<String>();

queue.offer("Jack");
queue.offer("Rose");
queue.offer("Trump");
System.out.println(queue);

String pollName = queue.poll();
System.out.println(pollName);
System.out.println(queue);

String peekName = queue.peek();
System.out.println(peekName);
System.out.println(queue);
}
}

<div class="se-preview-section-delimiter"></div>


Set

HashSet的特性和基本使用

HashSet是Set接口的子类,不包含重复元素相同元素,且无序。

HashSet下还有子类LinkedHashSet,可预测迭代顺序的Set集合。

/*
* HashSet,不包含重复元素相同元素,且无序.不提供索引,所以不能通过索引获取元素,只能通过迭代器访问数据.
*/
public class Demo01HashSet {

public static void main(String[] args) {

//创建集合对象
HashSet<String> set = new HashSet<String>();
//向集合中添加元素
set.add("Jack");
set.add("Rose");
set.add("Trump");
set.add("Obama");
set.add("Obama");

System.out.println(set);
//获取元素,只能用迭代器
Iterator<String> itr = set.iterator();

while(itr.hasNext()) {
String thisName = itr.next();
System.out.println(thisName);
}

System.out.println("================");
for (String thisName : set) {
System.out.println(thisName);
}
}
}

<div class="se-preview-section-delimiter"></div>


自定义类重写equals方法

自定义类需要满足咱们认为的效果,也就是不同的对象但是属性值相同就认为是同一个对象,在集合里只存其一的效果,就必须重写equals方法,且更改该方法里的比较规则.

/*
* 如果没有重写该equals方法,则比较地址值.
* 我们希望比较两个对象时,比较属性内容,所以重写该方法.
*/
@Override
public boolean equals(Object obj) {
System.out.println("equals方法被调用了");

//this:contains方法的参数对象         obj:集合当中老元素
//将Object类型的obj强转为子类类型
Person otherP = (Person)obj;

//比较姓名
if(!this.name.equals(otherP.name)) {
return false;
}
//比较年龄
if(this.age != otherP.age){
return false;
}
//如果所有属性值均相同,就返回true
return true;
}

<div class="se-preview-section-delimiter"></div>


HashSet判断元素唯一性规则

Set集合不能存放重复元素,其添加方法在添加时会判断是否有重复元素,有重复不添加,没重复则添加。
HashSet集合由于是无序的,其判断唯一的依据是元素类型的hashCode与equals方法的返回结果。规则如下:
先判断新元素与集合内已经有的旧元素的HashCode值
如果不同,判断元素不同。
如果相同,再判断equals比较结果,返回true则相同,返回false则仍然不同。
所以,使用HashSet存储自定义类型,如果没有重写该类的hashCode与equals方法,则判断重复时,使用的地址值,如果想通过内容比较元素是否相同,需要重写该类的hashcode与equals方法。
hashCode方法重写规则:将该对象的各个属性值hashCode相加即是整个对象的HashCode值。如果是基本类型,类似int,则直接返回int值就是该属性的hash值,如果是引用类型,类似String,就调用该成员变量的hashCode方法返回该成员变量hash值。这样可以根据对象的内容返回hashCode值,从而可以根据hashCode判断元素是否唯一。
但是由于在一些”碰巧的”情况下,可能出现内容不同但hashCode相同的情况,为了避免这些情况,我们加入一些干扰系数。
可是加入干扰系数后,仍会出现一些”碰巧”的情况,所以我们还要进行equals的二次判断

<div class="se-preview-section-delimiter"></div>


重写hashCode和equals方法

//没有重写equals方法,equals方法继承父类方法,通过判断地址值比较对象
@Override
public boolean equals(Object obj) {
System.out.println("equals方法被调用了");

//this:add方法的参数对象         obj:集合当中老元素
//将Object类型的obj强转为子类类型
Animal otherA = (Animal)obj;

//比较姓名
if(!this.name.equals(otherA.name)) {
return false;
}
//比较年龄
if(this.age != otherA.age){
return false;
}
//如果所有属性值均相同,就返回true
return true;
}

//没有重写hashCode方法时,hashCode方法继承父类方法,返回的是地址值
//重写hashCode方法,通过属性值返回一个整数数字
//即对象的hashCode值,就是各个属性的hashCode值之和
//引用数据类型属性,调用hashCode方法回去
//基本数值类型属性,直接就是数值本身
@Override
public int hashCode() {

//张三   18   >>   56*系数  +  18  = 74
//李四   56   >>   18*系数  +  56  = 74
//理想上,不同属性值应该返回不同的hashCode值,可以在每次结果后乘以一个固定系数,避免该情况发生

//定义变量,记录要返回的hashCode值
int thisHashCode = 0;

//获取name属性的hashCode值
thisHashCode += name.hashCode()*17;
//获取age数只给你的hashCode值
thisHashCode += age;

return thisHashCode;
}

<div class="se-preview-section-delimiter"></div>


TreeSet

自然排序 Comparable

二叉树 TreeSet:小的数存在左边(负数),大的数存在右边(正数),相等就不存(0)
compareTo in TreeSet : TreeSet如何存储取决于compareTo的返回值
return 0 : 重复的不存
return 负数:放左边
return 正数:放右边

<div class="se-preview-section-delimiter"></div>


//比较对象所有属性
public int compareTo(Goods goods) {
int num = this.price - goods.price;
int res = num == 0 ? this.name.compareTo(goods.name):num;
return res;
}


比较器排序 Comparator

实现图

排序总结



Java单列集合框架之总结&体系图



- Collection:所有单列集合的直接或间接接口,其指定了所有集合应该具备的基本功能。

- List:元素可重复,有序,有索引

- Set: 元素不能重复,没有索引

- ArrayList(重要):底层是数组结构。ArrayList的出现替代了Vector,增删慢,查找快。

- LinkedList(重要):底层是链表结构。同时对元素的增删操作效率很高。 去重时重写equals和hashCode

- HashSet(重要) :底层是哈希表结构。在不重复的基础上无序。

- TreeSet:底层是哈希表结构结合链表结构。在不重复的基础上可排列顺序 比较对象时实现Comparable的方法Compareto。

- LinkedHashSet:底层是哈希表结构结合链表结构。在不重复的基础上可预测迭代顺序。

比较器排序 Comparator



排序总结



Java单列集合框架之总结&体系图



- Collection:所有单列集合的直接或间接接口,其指定了所有集合应该具备的基本功能。

- List:元素可重复,有序,有索引

- Set: 元素不能重复,没有索引

- ArrayList(重要):底层是数组结构。ArrayList的出现替代了Vector,增删慢,查找快。

- LinkedList(重要):底层是链表结构。同时对元素的增删操作效率很高。 去重时重写equals和hashCode

- HashSet(重要) :底层是哈希表结构。在不重复的基础上无序。

- TreeSet:底层是哈希表结构结合链表结构。在不重复的基础上可排列顺序 比较对象时实现Comparable的方法Compareto。

- LinkedHashSet:底层是哈希表结构结合链表结构。在不重复的基础上可预测迭代顺序。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: