---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
集合框架二
1:Set
(1)Set的特点:
元素无序,唯一。
注意:这里的顺序是指存储和取出顺序。
2:HashSet
(1)HashSet:不保证元素的迭代顺序。并且,不保证该顺序恒久不变。
(2)怎么保证的呢?
HashSet底层数据结构是哈希表。
它依赖两个方法:hashCode()和equals()
顺序:
首先,判断hashCode()值是否相同。
相同:
继续走equals()方法,根据其返回值:
true:说明元素重复,不添加到集合。
false:说明元素不重复,添加到集合。
不同:直接添加到集合。
(3)怎么重写hashCode()和equals()方法呢?
hashCode():
把对象的所有成员变量值相加即可。
如果是基本类型,就加值。如果是引用类型,就加哈希值。
equals():
A:this==obj
B:!(obj instanceof Student)
C:所有成员变量的值比较。基本类型用==,引用类型用equals()。
如果不会,可以自动生成。
(4)案例:
HashSet存储字符串并遍历
/*
* HashSet存储字符串并遍历
*/
public class HashSetDemo {
public static void main(String[] args) {
// 创建集合对象
HashSet<String> hs = new HashSet<String>();
// 创建并添加元素
hs.add("hello");
hs.add("world");
hs.add("java");
hs.add("java");
// 遍历
for (String s : hs) {
System.out.println(s);
}
}
}
HashSet存储自定义对象并遍历
/*
* HashSet存储自定义对象。
* 需求:我们认为一个对象如果成员变量值都相同,则为同一个对象。
*
* 请思考:
* A:哪里出问题了
* 通过简单的分析,我们知道了在add方法出问题了。
* B:怎么解决
* 看源码
* 通过看源码:我们知道,最终的操作跟如下这个判断相关
* if(e.hash == hash && ((k = e.key) == key || key.equals(k)))
* {
* 唯一。
* }
* 分析条件:
* A:这个判断跟对象的hashCode()方法相关。
* B:这个判断跟equals()方法相关。
*
*
* 总结:
* HashSet如何保证元素的唯一性的呢?
* HashSet的底层数据结构是哈希表。
* 它依赖两个方法,hashCode()和equals()。
* 顺序:
* 首先,判断对象的hashCode()值是否相同。
* 相同:
* 继续走equals()。看返回值是true还是false
* A:如果是true,说明有元素重复。该元素不添加到集合。
* B:如果是false,说明元素不重复,该元素添加到集合。
* 不同:就直接添加到集合中了。
*/
public class HashSetDemo2 {
public static void main(String[] args) {
// 创建集合对象
HashSet<Student> hs = new HashSet<Student>();
// 创建元素对象
Student s1 = new Student("周霞", 26);
Student s2 = new Student("王玉", 36);
Student s3 = new Student("张敏", 20);
Student s4 = new Student("周霞", 26);
Student s5 = new Student("周霞", 66);
Student s6 = new Student("李玲", 16);
// 添加元素
hs.add(s1);
// hs.add(s1);
hs.add(s2);
hs.add(s3);
hs.add(s4);
hs.add(s5);
hs.add(s6);
// 遍历
for (Student s : hs) {
System.out.println(s.getName() + "***" + s.getAge());
}
}
}
针对自定义对象:
需求:如果对象的成员都相同,我们就认为是同一个元素。
3:TreeSet
(1)TreeSet:根据构造方法的不用,选择使用自然排序或者比较器排序。
按照实际的需求,可以对元素进行排序。并且保证唯一。
(2)怎么保证的呢?
排序:底层结构是二叉树。按照树节点进行存储和取出。
两种实现:
A:自然排序(元素具备比较性)
TreeSet的无参构造,要求对象所属的类实现Comparable接口。
B:比较器排序(集合具备比较性)
TreeSet的带参构造,要求构造方法接收一个实现了Comparator接口的对象。
唯一:根据返回值是否为0。
注意:
如果同时有两种方案,以谁为主呢?以比较器为主。
(3)案例:
TreeSet存储字符串并遍历
/*
* TreeSet可以对元素进行排序。
* 使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。
*/
public class TreeSetDemo {
public static void main(String[] args) {
// 创建集合对象
TreeSet<String> ts = new TreeSet<String>();
// 创建并添加元素
ts.add("hello");
ts.add("world");
ts.add("java");
ts.add("abcde");
ts.add("zone");
// ts.add("world");
// 遍历
for (String str : ts) {
System.out.println(str);
}
}
}
TreeSet存储Integer并遍历
/*
* TreeSet存储Integer类型的数据,保证唯一和排序
*/
public class TreeSetTest {
public static void main(String[] args) {
// 20,18,23,22,17,24,19,18,24
TreeSet<Integer> ts = new TreeSet<Integer>();
// 添加元素
ts.add(20);
ts.add(18);
ts.add(23);
ts.add(22);
ts.add(17);
ts.add(24);
ts.add(19);
ts.add(18);
ts.add(24);
// 遍历
for (Integer i : ts) {
System.out.println(i);
}
}
}
TreeSet存储自定义对象并遍历
/*
* TreeSet存储自定义对象。
* 保证元素有序和唯一。
*
* Exception in thread "main" java.lang.ClassCastException:
* cn.itcast_03.Student cannot be cast to java.lang.Comparable
*
* TreeSet保证元素排序有两种方式:
* A:自然顺序 让对象所属的类去实现Comparable接口。无参构造。
* B:比较器接口 Comparator。带参构造。
*
* 在自然排序中,又是如何保证排序的呢?
* 根据返回值看:
* 正 就说明元素比以前的元素大,往后放。
* 负 就说明元素比以前的元素小,往前放。
* 0 元素就不添加到集合中。着就是保证唯一性的原理。
*
* 需求:我想按照对象的年龄排序,从小到大排序。怎么做?
*
* 需求:我想按照姓名的长度排序,从小到大排序。怎么做?
*/
public class TreeSetDemo2 {
public static void main(String[] args) {
// 创建集合对象
TreeSet<Student> ts = new TreeSet<Student>();
// 创建元素对象
Student s1 = new Student("liudehua", 52);
Student s2 = new Student("chenglong", 60);
Student s3 = new Student("zhouxinchi", 44);
Student s4 = new Student("sunyanzi", 34);
Student s5 = new Student("linqingxia", 26);
Student s6 = new Student("linqingxia", 36);
Student s7 = new Student("linqing", 26);
Student s8 = new Student("linqingxia", 26);
// 添加元素
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
ts.add(s7);
ts.add(s8);
// 遍历
for (Student s : ts) {
System.out.println(s.getName() + "***" + s.getAge());
}
}
}
4:Collection体现的集合总结
Collection
|--List
|--ArrayList
底层数据结构是数组,查询快,增删慢
线程不安全,效率高。
|--LinkedList
底层数据结构是链表,查询慢,增删快
线程不安全,效率高。
|--Vector
底层数据结构是数组,查询快,增删慢
线程安全,效率低。
|--Set 唯一
|--HashSet
底层数据结构是哈希表。
如何保证元素唯一性呢?
依赖两个方法。hashCode()和equals()。
以后都自动生成。
|--TreeSet
底层数据结构是二叉树。
如何保证元素唯一性呢?如何保证元素排序呢?
根据返回值是否是0,判断元素是否重复。
排序有两种方案:
元素具备比较性 实现Comparable接口
集合具备比较性 实现Comparator接口
5:在集合中的数据结构问题
ArrayXxx:底层数据结构是数组。查询快,增删慢。
LinkedXxx:底层数据结构是链表。查询慢,增删快。
HashXxx:底层数据结构是哈希表。跟两个有关。hashCode()和equals()
TreeXxx:底层数据结构是二叉树。两种排序方式。Comparable接口和Comparator接口
6:什么时候,使用哪种Collection集合。
元素唯一吗?
唯一:
Set
需要排序吗?
需要:TreeSet
不需要:HashSet
不知道,用HashSet。
不唯一:
List
需要安全码?
需要:Vector
不需要:ArrayList和LinkedList
查询多:ArrayList
增删多;LinkedList
不知道,用ArrayList。
7:Collections
(1)Collections是针对Collection集合操作的工具类。
(2)面试题:
Collection和Collections的区别?
Collection:是Collection集合的顶层接口,定义了Collection集合的共性方法。
Collections:是一个类,定义了针对Collection集合操作的功能。有排序,查找,反转等。
(3)功能:
排序public static void sort(List list)
查找public static <T> int binarySearch(List list,T key)
反转public static void reverse(List list)
最值public static T max(Collection coll)
随机置换public static void shuffle(List list)
8:Map
(1)Map是一个键值对形式的集合。它的元素都是有键和值组成。
(2)Map和Collection的区别?(面试题)
A:Map 是由键值对组成的集合,Map的键是唯一的,值可以重复。
B:Collection 是有单列数据组成的集合,它的儿子List是可以重复的,Set是唯一的。
(3)HashMap和Hashtable的区别?(面试题)
HashMap:线程不安全,效率高。允许null键和值。
Hashtable:线程安全,效率低。不允许null键和值。
(4)Map的功能:(自己补齐)
A:添加功能
V put(K key,V value):当key在集合中不存在时,添加元素,当Key在集合中存在时,替换元素。
B:判断功能
boolean containsKey(Object key):判断指定的键是否在集合中存在
boolean containsValue(Object value):判断指定的值是否在集合中存在
boolean isEmpty():判断集合是否为空
C:删除功能
void clear():清除所有键值对数据
V remove(Object key):根据指定的键删除键值对。
D:获取功能
Set<Map.Entry<K,V>> entrySet():键值对对象的集合
Object get(Object key):根据键获取值
Set<K> keySet():所有键的集合
Collection<V> values():所有值的集合
E:长度功能
int size()
(5)Map的两种遍历方式
A:丈夫找妻子
a:把所有丈夫给集中起来。Set<K> keySet()
b:遍历丈夫集合,获取到每一个丈夫。迭代器,增强for
c:让丈夫去找妻子。get(Object key)
代码实现:
A:丈夫找妻子
/*
* Object get(Object key):根据键获取值
* Map集合的遍历。
* 方式1:丈夫找妻子
* A:把所有丈夫给集中起来。Set<K> keySet()
* B:遍历丈夫集合,获取到每一个丈夫。迭代器,增强for
* C:让丈夫去找妻子。get(Object key)
*/
public class MapDemo3 {
public static void main(String[] args) {
// 创建集合对象
Map<String, String> map = new HashMap<String, String>();
// 创建并添加元素
map.put("杨过", "小龙女");
map.put("郭靖", "黄蓉");
map.put("梁山伯", "祝英台");
map.put("牛郎", "织女");
// 键的集合
Set<String> set = map.keySet();
for (String str : set) {
System.out.println(str);
}
System.out.println("---------");
// 值的集合
Collection<String> con = map.values();
for (String str : con) {
System.out.println(str);
}
System.out.println("---------");
// 根据键获取值
// Object get(Object key):根据键获取值
System.out.println(map.get("郭靖"));
System.out.println(map.get("牛郎"));
System.out.println(map.get("田野"));
System.out.println("---------");
// 遍历
// A:把所有丈夫给集中起来。Set<K> keySet()
Set<String> husbandSet = map.keySet();
// B:遍历丈夫集合,获取到每一个丈夫。迭代器,增强for
for (String husband : husbandSet) {
// C:让丈夫去找妻子。get(Object key)
String wife = map.get(husband);
System.out.println(husband + "***" + wife);
}
}
}
B:根据结婚证找丈夫和妻子
/*
* Map集合的遍历。
* 方式2:通过结婚证找丈夫和妻子。
* A:获取所有结婚证的集合。Set<结婚证> entrySet()
* class 结婚证<K,V>
* {
* private K key;
* private V value;
*
* public 结婚证(K key,V value)
* {
* this.key = key;
* this.value = value;
* }
*
* public K getKey()
* {
* return key;
* }
*
* public V getValue()
* {
* return value;
* }
* }
* B:遍历结婚证集合,获取到每一个结婚证对象。迭代器,增强for。
* C:通过结婚证对象获取丈夫和妻子。
*/
public class MapDemo4 {
public static void main(String[] args) {
// 创建集合对象
Map<String, String> map = new HashMap<String, String>();
// 创建并添加元素
map.put("杨过", "小龙女");
map.put("郭靖", "黄蓉");
map.put("梁山伯", "祝英台");
map.put("牛郎", "织女");
// 获取结婚证的集合
// Set<Map.Entry<K,V>> entrySet():键值对对象的集合。
Set<Map.Entry<String, String>> set = map.entrySet();
// 遍历结婚证集合,获取到每一个结婚证对象
for (Map.Entry<String, String> me : set) {
// 通过结婚证对象获取丈夫和妻子。
String key = me.getKey();
String value = me.getValue();
System.out.println(key + "***" + value);
}
}
}
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------