您的位置:首页 > 理论基础 > 数据结构算法

重踏学习Java路上_Day17(登录注册案例,Set集合,Collection集合总结,在集合中常见的数据结构)

2015-07-04 15:22 691 查看
1:登录注册案例(理解)



需求:用户登录注册案例。

按照如下的操作,可以让我们更符号面向对象思想
A:有哪些类呢?
B:每个类有哪些东西呢?
C:类与类之间的关系是什么呢?

分析:
A:有哪些类呢?
用户类
测试类
B:每个类有哪些东西呢?
用户类:
成员变量:用户名,密码
构造方法:无参构造
成员方法:getXxx()/setXxx()
登录,注册

假如用户类的内容比较对,将来维护起来就比较麻烦,为了更清晰的分类,我们就把用户又划分成了两类
用户基本描述类
成员变量:用户名,密码
构造方法:无参构造
成员方法:getXxx()/setXxx()
用户操作类
登录,注册
测试类:
main方法。
C:类与类之间的关系是什么呢?
在测试类中创建用户操作类和用户基本描述类的对象,并使用其功能。

分包:
A:功能划分
B:模块划分
C:先按模块划分,再按功能划分

今天我们选择按照功能划分:
用户基本描述类包 cn.itcast.pojo
用户操作接口 cn.itcast.dao
用户操作类包 cn.itcast.dao.impl
今天是集合实现,过几天是IO实现,再过几天是GUI实现,就业班我们就是数据库实现
用户测试类 cn.itcast.test

2:Set集合(理解)
(1)Set集合的特点
无序,唯一 (一个不包含重复元素的 collection。因为无序,所以没有索引,所以没有get(index)方法,只有list接口才有get(index))
(2)HashSet集合(掌握)
A:底层数据结构是哈希表(是一个元素为链表的数组)
B:哈希表底层依赖两个方法:hashCode()和equals(),哈希表保证了元素的唯一性
执行顺序:
首先比较哈希值是否相同
相同:继续执行equals()方法
返回true:元素重复了,不添加
返回false:直接把元素添加到集合
不同:就直接把元素添加到集合
C:如何保证元素唯一性的呢?
由hashCode()和equals()保证的
D:开发的时候,重写hashCode()与equal()代码非常的简单,自动生成即可。(如果是自己重写代码,一般是返回值=基本类型*特别值+引用类型的.hashCode(),这样生成)
E:HashSet的子类:LinkedHashSet<E> , 特点:具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现,此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。本子类没有任何特有方法,继承自HashSet所有方法,所以可以直接用父类任何方法。哈希表保证唯一性,链表保证有序性。
F:HashSet存储字符串并遍历 :除了不能用普通for方法,其他一样,因为set无序没有get()方法,所以不能有普通for,只能用增强for,与Iterator
G:HashSet存储自定义对象并遍历(对象的成员变量值相同即为同一个元素) 重写equal与hashcode方法

(3)TreeSet集合
A:底层数据结构是红黑树(是一个自平衡的二叉树),TreeMap;
B:保证元素的排序方式
a:自然排序(元素具备比较性)
让元素所属的类实现Comparable接口
b:比较器排序(集合具备比较性)
让集合构造方法接收Comparator的实现类对象
C:把我们讲过的代码看一遍即可
(4)案例:(代码在随笔名称:TreeSet概述(源码和内部图 进行解析))
A:获取无重复的随机数
B:键盘录入学生按照总分从高到底输出

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

/*
* HashSet:存储字符串并遍历
* 问题:为什么存储字符串的时候,字符串内容相同的只存储了一个呢?
* 通过查看add方法的源码,我们知道这个方法底层依赖 两个方法:hashCode()和equals()。
* 步骤:
* 首先比较哈希值
* 如果相同,继续走,比较地址值或者走equals()
* 如果不同,就直接添加到集合中
* 按照方法的步骤来说:
* 先看hashCode()值是否相同
* 相同:继续走equals()方法
* 返回true: 说明元素重复,就不添加
* 返回false:说明元素不重复,就添加到集合
* 不同:就直接把元素添加到集合
* 如果类没有重写这两个方法,默认使用的Object()。一般来说不同相同。
* 而String类重写了hashCode()和equals()方法,所以,它就可以把内容相同的字符串去掉。只留下一个。
*/

HashSet add()方法源码解析:用于理解为什么set接口只允许唯一元素进入Set,而不能重复元素
interface Collection {
...
}

interface Set extends Collection {
...
}

class HashSet implements Set {
private static final Object PRESENT = new Object();
private transient HashMap<E,Object> map;

public HashSet() {
map = new HashMap<>();
}

public boolean add(E e) { //e=hello,world
return map.put(e, PRESENT)==null;
}
}

class HashMap implements Map {
public V put(K key, V value) { //key=e=hello,world

//看哈希表是否为空,如果空,就开辟空间
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}

//判断对象是否为null
if (key == null)
return putForNullKey(value);

int hash = hash(key); //和对象的hashCode()方法相关

//在哈希表中查找hash值
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
//这次的e其实是第一次的world
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
//走这里其实是没有添加元素
}
}

modCount++;
addEntry(hash, key, value, i); //把元素添加
return null;
}

transient int hashSeed = 0;

final int hash(Object k) { //k=key=e=hello,
int h = hashSeed;
if (0 != h && k instanceof String) {
return sun.misc.Hashing.stringHash32((String) k);
}

h ^= k.hashCode(); //这里调用的是对象的hashCode()方法

// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
}
hs.add("hello");
hs.add("world");
hs.add("java");
hs.add("world");
-------------------------------------------------------------------------------------------------------

HashSet子类:LinkedHashSet

/*
* LinkedHashSet:底层数据结构由哈希表和链表组成。
* 哈希表保证元素的唯一性。
* 链表保证元素有素。(存储和取出是一致)
*/
public class LinkedHashSetDemo {
public static void main(String[] args) {
// 创建集合对象
LinkedHashSet<String> hs = new LinkedHashSet<String>();

// 创建并添加元素
hs.add("hello");
hs.add("world");
hs.add("java");
hs.add("world");
hs.add("java");

// 遍历
for (String s : hs) {
System.out.println(s);
}
}
}
--------------------------------------------------------------------------------------------------------
3:Collection集合总结(掌握)
Collection
|--List 有序(存储顺序与读取数据顺序不一致),可重复
|--ArrayList
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高
|--Vector
底层数据结构是数组,查询快,增删慢。
线程安全,效率低
|--LinkedList
底层数据结构是链表,查询慢,增删快。
线程不安全,效率高
|--Set 无序,唯一
|--HashSet
底层数据结构是哈希表。
如何保证元素唯一性的呢?
依赖两个方法:hashCode()和equals()
开发中自动生成这两个方法即可
|--LinkedHashSet
底层数据结构是链表和哈希表
由链表保证元素有序
由哈希表保证元素唯一
|--TreeSet
底层数据结构是红黑树。
如何保证元素排序的呢?
自然排序
比较器排序
如何保证元素唯一性的呢?
根据比较的返回值是否是0来决定

4:针对Collection集合我们到底使用谁呢?(掌握)
唯一吗?
是:Set
排序吗?
是:TreeSet
否:HashSet
如果你知道是Set,但是不知道是哪个Set,就用HashSet。

否:List
要安全吗?
是:Vector
否:ArrayList或者LinkedList
查询多:ArrayList
增删多:LinkedList
如果你知道是List,但是不知道是哪个List,就用ArrayList。

如果你知道是Collection集合,但是不知道使用谁,就用ArrayList。

如果你知道用集合,就用ArrayList。

5:在集合中常见的数据结构(掌握)
ArrayXxx:底层数据结构是数组,查询快,增删慢
LinkedXxx:底层数据结构是链表,查询慢,增删快
HashXxx:底层数据结构是哈希表。依赖两个方法:hashCode()和equals()
TreeXxx:底层数据结构是二叉树。两种方式排序:自然排序和比较器排序

6.ArrayList集合的toString()方法源码解析
代码:
Collection c = new ArrayList();
c.add("hello");
c.add("world");
c.add("java");

System.out.println(c);

为什么c输出的不是地址值呢?

java.util
类 ArrayList<E>
java.lang.Object
java.util.AbstractCollection<E> -----------------这里才有toString()的实现方法
java.util.AbstractList<E> ----------------- 这里也没有
java.util.ArrayList<E> ---------------- 这里没有

A:Collection c = new ArrayList();
这是多态,所以输出c的toString()方法,其实是输出ArrayList的toString()
B:看ArrayList的toString()
而我们在ArrayList里面却没有发现toString()。
以后遇到这种情况,也不要担心,你认为有,它却没有,就应该去它父亲里面看看。
C:toString()的方法源码

public String toString() {
Iterator<E> it = iterator(); //集合本身调用迭代器方法,得到集合迭代器
if (! it.hasNext())
return "[]";

StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
E e = it.next(); //e=hello,world,java
sb.append(e == this ? "(this Collection)" : e);
if (! it.hasNext())
//[hello, world, java]
return sb.append(']').toString();
sb.append(',').append(' ');
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: