您的位置:首页 > 编程语言 > Java开发

Java集合框架之Set

2017-04-30 18:57 204 查看
1.Set接口概述

一个不包含重复元素的collection。

Set集合的特点

        无序(存储顺序和取出顺序不一致),唯一

import java.util.HashSet;
import java.util.Set;

/*
* Collection
* 		|--List
* 			有序(存储顺序和取出顺序一致),可重复
* 		|--Set
* 			无序(存储顺序和取出顺序不一致),唯一
*
* HashSet:它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。
* 注意:虽然Set集合的元素无序,但是,作为集合来说,它肯定有它自己的存储顺序,
* 而你的顺序恰好和它的存储顺序一致,这代表不了有序,你可以多存储一些数据,就能看到效果。
*/
public class SetDemo {
public static void main(String[] args) {
// 创建集合对象
Set<String> set = new HashSet<String>();

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

// 增强for
for (String s : set) {
System.out.println(s);
}
}
}


2.HashSet集合

        A:底层数据结构是哈希表(是一个元素为链表的数组)

        B:哈希表底层依赖两个方法:hashCode()和equals()
hashCode方法的主要作用是为了配合基于散列的集合一起正常运行,这样的散列集合包括HashSet、HashMap以及HashTable。

equals()和hashCode()详解:http://blog.csdn.net/u014401141/article/details/74857459

import java.util.HashSet;

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

// 遍历集合
for (String s : hs) {
System.out.println(s);
}
}
}


执行顺序:

            首先比较哈希值是否相同

                相同:继续执行equals()方法

                    返回true:元素重复了,不添加

                    返回false:直接把元素添加到集合

                不同:就直接把元素添加到集合

        C:如何保证元素唯一性的呢?

            由hashCode()和equals()保证的

        D:开发的时候,代码非常的简单,自动生成即可。

重写对象的hashCode(),equals()方法

public class Dog {
private String name;
private int age;
private String color;
private char sex;

public Dog() {
super();
}

public Dog(String name, int age, String color, char sex) {
super();
this.name = name;
this.age = age;
this.color = color;
this.sex = sex;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getColor() {
return color;
}

public void setColor(String color) {
this.color = color;
}

public char getSex() {
return sex;
}

public void setSex(char sex) {
this.sex = sex;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((color == null) ? 0 : color.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + sex;
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Dog other = (Dog) obj;
if (age != other.age)
return false;
if (color == null) {
if (other.color != null)
return false;
} else if (!color.equals(other.color))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (sex != other.sex)
return false;
return true;
}

}

import java.util.HashSet;

/*
* HashSet集合存储自定义对象并遍历。如果对象的成员变量值相同即为同一个对象
*
* 注意了:
* 		你使用的是HashSet集合,这个集合的底层是哈希表结构。
* 		而哈希表结构底层依赖:hashCode()和equals()方法。
* 		如果你认为对象的成员变量值相同即为同一个对象的话,你就应该重写这两个方法。
* 		如何重写呢?不同担心,自动生成即可。
*/
public class DogDemo {
public static void main(String[] args) {
// 创建集合对象
HashSet<Dog> hs = new HashSet<Dog>();

// 创建狗对象
Dog d1 = new Dog("秦桧", 25, "红色", '男');
Dog d2 = new Dog("高俅", 22, "黑色", '女');
Dog d3 = new Dog("秦桧", 25, "红色", '男');
Dog d4 = new Dog("秦桧", 20, "红色", '女');
Dog d5 = new Dog("魏忠贤", 28, "白色", '男');
Dog d6 = new Dog("李莲英", 23, "黄色", '女');

// 添加元素
hs.add(d1);
hs.add(d2);
hs.add(d3);
hs.add(d4);
hs.add(d5);
hs.add(d6);

// 遍历
for (Dog d : hs) {
System.out.println(d.getName() + "---" + d.getAge() + "---"
+ d.getColor() + "---" + d.getSex());
}
}
}


        E:HashSet存储字符串并遍历

        F:HashSet存储自定义对象并遍历(对象的成员变量值相同即为同一个元素)

4.LinkedHashSet

  LinkedHashSet:底层数据结构由哈希表和链表组成。

  哈希表保证元素的唯一性。

  链表保证元素有素。(存储和取出是一致)

import java.util.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);
}
}
}


5.TreeSet集合

        A:底层数据结构是红黑树(是一个自平衡的二叉树)

        B:保证元素的排序方式

            a:自然排序(元素具备比较性)

                让元素所属的类实现Comparable接口

                真正的比较是依赖于元素的compareTo()方法,而这个方法是定义在 Comparable里面的。

              所以,你要想重写该方法,就必须是先 Comparable接口。这个接口表示的就是自然排序。

            b:比较器排序(集合具备比较性)

                让集合构造方法接收Comparator的实现类对象



import java.util.TreeSet;

/*
* TreeSet:能够对元素按照某种规则进行排序。
* 排序有两种方式
* A:自然排序
* B:比较器排序
* TreeSet集合的特点:排序和唯一
* 通过观察TreeSet的add()方法,我们知道最终要看TreeMap的put()方法。
*/
public class TreeSetDemo {
public static void main(String[] args) {
// 创建集合对象
// 自然顺序进行排序
TreeSet<Integer> ts = new TreeSet<Integer>();

// 创建元素并添加
// 20,18,23,22,17,24,19,18,24
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);
}
}
}

/*
* 如果一个类的元素要想能够进行自然排序,就必须实现自然排序接口
*/
public class Student implements Comparable<Student> {
private String name;
private int age;

public Student() {
super();
}

public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

@Override
public int compareTo(Student s) {
// return 0;
// return 1;
// return -1;

// 这里返回什么,其实应该根据我的排序规则来做
// 按照年龄排序,主要条件
int num = this.age - s.age;
// 次要条件
// 年龄相同的时候,还得去看姓名是否也相同
// 如果年龄和姓名都相同,才是同一个元素
int num2 = num == 0 ? this.name.compareTo(s.name) : num;
return num2;
}
}


6.HashSet集合存储自定义对象并遍历。
–如果对象的成员变量值相同即为同一个对象



7:Collection集合总结(掌握)

    Collection

        |--List    有序,可重复

            |--ArrayList

                底层数据结构是数组,查询快,增删慢。

                线程不安全,效率高

            |--Vector

                底层数据结构是数组,查询快,增删慢。

                线程安全,效率低

            |--LinkedList

                底层数据结构是链表,查询慢,增删快。

                线程不安全,效率高

        |--Set    无序,唯一

            |--HashSet

                底层数据结构是哈希表。

                如何保证元素唯一性的呢?

                    依赖两个方法:hashCode()和equals()

                    开发中自动生成这两个方法即可

                |--LinkedHashSet

                    底层数据结构是链表和哈希表

                    由链表保证元素有序

                    由哈希表保证元素唯一

            |--TreeSet

                底层数据结构是红黑树。

                如何保证元素排序的呢?

                    自然排序

                    比较器排序

                如何保证元素唯一性的呢?

                    根据比较的返回值是否是0来决定

                    

8:针对Collection集合我们到底使用谁呢?(掌握)

    唯一吗?

        是:Set

            排序吗?

                是:TreeSet

                否:HashSet

        如果你知道是Set,但是不知道是哪个Set,就用HashSet。

            

        否:List

            要安全吗?

                是:Vector

                否:ArrayList或者LinkedList

                    查询多:ArrayList

                    增删多:LinkedList

        如果你知道是List,但是不知道是哪个List,就用ArrayList。

    

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

    

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

    

9:在集合中常见的数据结构(掌握)

    ArrayXxx:底层数据结构是数组,查询快,增删慢

    LinkedXxx:底层数据结构是链表,查询慢,增删快

    HashXxx:底层数据结构是哈希表。依赖两个方法:hashCode()和equals()

    TreeXxx:底层数据结构是二叉树。两种方式排序:自然排序和比较器排序
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息