javaSE_集合与队列(set)

 Set是个接口类,有很多派生类:

在插入数据时,它通过数据的hashCode方法获取一个值,可以理解为其内部有一个maphashCode为键,值为值。因此添加两个一样的数据时,第二个会失败。

HashSet类按照哈希算法来存取集合中的对象,存取速度比较快

TreeSet类实现了SortedSet接口,能够对集合中的对象进行排序。

 

1) HashSet

public static void set_Integer(){

Set<Integer> nums = new HashSet<>();

boolean bR1 = nums.add(10);

boolean bR2 = nums.add(30);

boolean bR3 = nums.add(20);

boolean bR4 = nums.add(40);

boolean bR5 = nums.add(30);

System.out.println(bR1);

System.out.println(bR2);

System.out.println(bR3);

System.out.println(bR4);

System.out.println(bR5);

for (Integer num : nums){

System.out.println(num);

}

}

输出:

true

true

true

true

false

20

40

10

30

可见两点:

1.set内存储的内容是无序的,并不是插入时的顺序;

2.相同的值不能插入add方法返回的是false

 

如果是类对象,判断两个对象是否一样时,通过类的hashCodeequals方法共同来判断。

如:定义一个Student类,重写其hashCodeequals方法,都只使用name成员变量来判断。

public class Student {

private Integer age;

private String name;

public Integer getAge() {

return age;

}

public void setAge(Integer age) {

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public Student(Integer age, String name) {

super();

this.age = age;

this.name = name;

}

public Student() {

super();

}

@Override

public int hashCode() {

final int prime = 31;

int result = 1;

//result = prime * result + ((age == null) ? 0 : age.hashCode());

result = prime * result + ((name == null) ? 0 : name.hashCode());

return result;

}

@Override

public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())

return false;

Student other = (Student) obj;

//if (age == null) {

//if (other.age != null)

//return false;

//} else if (!age.equals(other.age))

//return false;

if (name == null) {

if (other.name != null)

return false;

} else if (!name.equals(other.name))

return false;

return true;

}

}

 

public static void set_Student(){

Set<Student> students = new HashSet<>();

Student stud1 = new Student(20, "张三");

Student stud2 = new Student(22, "李四");

Student stud3 = new Student(21, "王五");

Student stud4 = new Student(20, "李四");

students.add(stud1);

students.add(stud2);

students.add(stud3);

students.add(stud4);

for (Student stdu : students){

System.out.println(stdu.getName() + " -- " + stdu.getAge());

}

}

输出:

王五 -- 21

李四 -- 22

张三 -- 20

可见,姓名相同的对象没有添加成功。

 

2) LinkedHashSet

LinkedHashSetHashSet的派生类,主要的区别在于:

HashSet中的数据是无序的(和插入时顺序无关)

LinkedHashSet中的数据是按插入时的顺序存储的。

如:

Set<Integer> nums = new HashSet<>();

for (int i = 10; i < 100000; i++){

nums.add(i);

}

nums.add(6 );

nums.add(5);

for (Integer num : nums){

System.out.println(num);

}

输出的值不是连续的:

 

Set<Integer> nums = new LinkedHashSet<>();

for (int i = 10; i < 100000; i++){

nums.add(i);

}

nums.add(6 );

nums.add(5);

for (Integer num : nums){

System.out.println(num);

}

输出插入时的顺序:

 

 

3) TreeSet

其内部使用一个红黑树算法来维护元素的顺序。

即:其内部数据是排序的。

l 方法

TreeSet<Integer> nums = new TreeSet<>(new IntComparator());

nums.add(6);

nums.add(5);

nums.add(3);

nums.add(7);

nums.add(1);

nums.add(2);

for (Integer num : nums){

System.out.print("\t" + num);

}

System.out.println("");

System.out.println(nums.toString());// [7, 6, 5, 3, 2, 1]

System.out.println(nums.first());// 第一个元素

System.out.println(nums.last());// 最后一个元素

System.out.println(nums.lower(2));// 元素2前面的元素值“3”

System.out.println(nums.higher(2));// 元素2后面的元素值“1”

TreeSet<Integer> subSet=(TreeSet<Integer>) nums.subSet(5, 2);// 值在[52)间的值(包含5,不包含2

System.out.println(subSet.toString());// [5, 3]

TreeSet<Integer> headSet = (TreeSet<Integer>) nums.headSet(3);// 值在3前面的值(不包含3

System.out.println(headSet.toString());// [7, 6, 5]

TreeSet<Integer> tailSet = (TreeSet<Integer>) nums.tailSet(3);// 值在3后面的值(包含3

System.out.println(tailSet.toString());// [3, 2, 1]

 

l Int

Set<Integer> nums = new TreeSet<>();

nums.add(6);

nums.add(5);

nums.add(3);

nums.add(7);

for (Integer num : nums){

System.out.print(num + "\t");

}

输出: 3567

默认增序排序,也可以自定义排序规则:

定义一个类,创建TreeSet时由构造函数将排序类传入:

public class IntComparator implements Comparator<Integer>{

@Override

public int compare(Integer arg0, Integer arg1) {

return arg1-arg0;

}

}

使用时如下:

Set<Integer> nums = new TreeSet<>(new IntComparator());

输出 7653

 

l String

数字,如果是字串,则是使用的hashcode进行的比较,修改为降序如下:

public class StringComparator implements Comparator<String>{

@Override

public int compare(String o1, String o2) {

return o2.hashCode() - o1.hashCode();

}

}

使用时如下:

Set<String> strs = new TreeSet<>(new StringComparator());

strs.add("李四");

strs.add("张三");

strs.add("王五");

strs.add("a");

strs.add("d");

strs.add("b");

for (String str : strs){

System.out.print("\t" + str);

}

输出 王五 李四 张三 d b a

 

l Date

Set<Date> dates = new TreeSet<>();

try {

String format = "yyyy-MM-dd HH:mm:ss";

Date date1 = stringToDate("2016-5-1 13:24:5", format);

Date date2 = stringToDate("2016-5-3 13:24:5", format);

Date date3 = stringToDate("2016-5-2 13:24:5", format);

dates.add(date1);

dates.add(date2);

dates.add(date3);

for (Date date : dates){

System.out.println(dateToString(date, format));

}

} catch (ParseException e) {

e.printStackTrace();

}

输出

2016-05-01 13:24:05

2016-05-02 13:24:05

2016-05-03 13:24:05

 

序:

public class DateComparator implements Comparator<Date>{

@Override

public int compare(Date o1, Date o2) {

if (o2.before(o1)){

return -1;

}

return 1;

}

}

Set<Date> dates = new TreeSet<>(new DateComparator());

try {

String format = "yyyy-MM-dd HH:mm:ss";

Date date1 = stringToDate("2016-5-1 13:24:5", format);

Date date2 = stringToDate("2016-5-3 13:24:5", format);

Date date3 = stringToDate("2016-5-2 13:24:5", format);

dates.add(date1);

dates.add(date2);

dates.add(date3);

for (Date date : dates){

System.out.println(dateToString(date, format));

}

} catch (ParseException e) {

e.printStackTrace();

}

输出

2016-05-03 13:24:05

2016-05-02 13:24:05

2016-05-01 13:24:05

 

4) EunmSet

枚举set,暂时没找到使用场景,在网上找了一段说明,如下:

1EnumSet中所有值都必须是指定枚举类型的值,它的元素也是有序的,以枚举值在枚举类的定义顺序来决定集合元素的顺序。

2EnumSet集合不允许加入null元素,否则会抛出NullPointerException异常。

3EnumSet类没有暴露任何构造器来创建该类的实例,程序应该通过它提供的static方法来创建EnumSet对象,常用的static方法如下:

static EnumSet allOfClass elementType):创建一个包含指定枚举类里所有枚举值的EnumSet集合。

static EnumSet complementOfEnumSet s):创建一个其元素类型与指定EnumSet里元素类型相同的EnumSet,新的EnumSet集合包含原EnumSet集合所不包含的、此枚举类剩下的枚举值。

static EnumSet copyOfcollection c):使用一个普通集合来创建EnumSet集合。

static EnumSet copyOfEnumSet e:创建一个与指定EnumSet具有相同元素类型、相同集合元素的EnumSet

static EnumSet noneOfClass elementType):创建一个元素类型为指定枚举类型的空EnumSet.

static EnumSet of(E first,E...rest):创建一个包含一个或多个枚举值的EnumSet,传入的多个枚举值必须属于同一个枚举类。

static EnumSet rangeE fromE to):创建包含从from枚举值,到to枚举值范围内所有枚举值的EnumSet集合。

public static void main(String[] args) {

    EnumSet e1=EnumSet.allOf(Season1.class);//创建一个EnumSet集合,集合元素就是Season里的全部枚举值

  System.out.println(e1);//输出[SPRING, SUMMER, FALL, WINTER]

    EnumSet e2=EnumSet.noneOf(Season1.class);//创建一个EnumSet空集合,指定其集合元素是season1的枚举值

  e2.add(Season1.WINTER);

  e2.add(Season1.SPRING);

  System.out.println(e2);//输出[SPRING, WINTER]

   EnumSet e3=EnumSet.of(Season1.SUMMER, Season1.WINTER);//以指定枚举值创建EnumSet集合

  System.out.println(e3);//输出[SUMMER, WINTER]

  EnumSet e4=EnumSet.range(Season1.SUMMER, Season1.WINTER);

  System.out.println(e4);//输出[SUMMER, FALL, WINTER]

  EnumSet e5=EnumSet.complementOf(e4);

  System.out.println(e5);//输出[SPRING]

}

 

遍历集合

主要有两种方式,for,以及迭代器:

如:

Set<Integer> nums = new HashSet<>();

nums.add(10);

nums.add(30);

for (Integer num : nums){

System.out.print(num + "\t");

}

 

Iterator<Integer> iter = nums.iterator();

while (iter.hasNext()){

Integer num = iter.next();

System.out.print(num + "\t");

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值