概述

  List、Set接口都是继承于Collection主接口,而Map为独立接口

  1、List接口下有ArrayList、Vector、LinkedList实现类

  2、Set接口下有HashSet、LinkedHashSet、TreeSet实现类

  3、Map下有HashMap、LinkedHashMap、Hashtable、TreeMap实现类

特点

  Collection接口:

    ——List接口 有序,可重复    

      ArrayList

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

      缺点: 线程不安全,效率高

      LinkedList

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

      缺点: 线程不安全,效率高

        Vector

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

      缺点: 线程安全,效率低

    ——Set 无序,唯一

      HashSet

      底层数据结构是哈希表。(无序,唯一)

      如何来保证元素唯一性?

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

       LinkedHashSet

      底层数据结构是链表和哈希表 (FIFO插入有序,且唯一)

      原因如下两点:

      答:1.由链表保证元素有序

        2.由哈希表保证元素唯一

      TreeSet

      底层数据结构是红黑树。(唯一,且有序)

      1. 如何保证元素排序的呢?

      答:1.自然排序

        2.比较器排序

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

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

针对于Collection集合我们到底如何使用呢?(重点掌握)

  唯一吗?

    是:Set

      排序吗?

        是:TreeSet或LinkedHashSet
          否:HashSet
          如果你知道是Set,但是不知道是哪个Set,就用HashSet。

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

    否:List

      要安全吗?

        是:Vector
          否:ArrayList或者LinkedList

          查询多:ArrayList
            增删多:LinkedList

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

  Map接口:

      Map接口有三个重要的实现类,分别是 HashMap、LinkedHashMap、Hashtable

      1、TreeMap是有序的,HashMap和Hashtable是无序的。

      2、Hashtable的方法是同步的,底层源码方法有(synchronized)这是两者主要区别。

      这就意味着:

      3、Hashtable是线程安全,HashMap是非线程安全。

      4、HashMap效率较高,Hashtable效率较低.

重点问题重点分析

(一)、TreeSet,LinkedHashSet and HashSet 的区别

1.介绍

TreeSet,LinkedHashSet and HashSet 在Java中都是实现Set的数据结构

1.TreeSet的主要功能用于排序

2.LinkedHashSet的主要功能用于保证FIFO即有序的集合(先进先出)

3.HashSet只是通用的存储数据的集合

2.相同点

重复元素:因为三者都实现Set interface,所以三者都不包含重复元素.

线程安全:三者都不是线程安全的,如果要使用线程安全可以Collections.synchronizedSet()

3.不同点

性能和速度:HashSet插入数据最快,其次LinkHashSet,最慢的是TreeSet因为内部实现排序。

排序:HashSet不保证有序,LinkHashSet保证FIFO即按插入顺序排序,TreeSet安装内部实现排序,也可以自定义排序规则。

Null:HashSet和LinkHashSet允许存在null数据,但是TreeSet中插入null数据时会报NullPointerException异常。

4.不多说了上代码进行比较!

package com.jia.set;

import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.TreeSet; public class SetDemo { public static void main(String args[]) { HashSet<String> hashSet = new HashSet<>();
LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
TreeSet<String> treeSet = new TreeSet<>(); for (String data : Arrays.asList("B", "A", "D", "C", "E")) {
hashSet.add(data);
linkedHashSet.add(data);
treeSet.add(data);
} // 不保证有序
System.out.println("HashSet排序 :" + hashSet); // FIFO保证安装插入顺序排序
System.out.println("LinkedHashSet插入顺序排序 :" + linkedHashSet); // 内部实现排序
System.out.println("TreeSet内部排序 :" + treeSet); } }

运行结果:

HashSet排序 :[A, B, C, D, E]
LinkedHashSet插入顺序排序 :[B, A, D, C, E]
TreeSet内部排序 :[A, B, C, D, E]

(二)、TreeSet的两种排序方式比较

1.排序的引入  (以基本数据类型的排序为例) 

package com.jia.set;

import java.util.TreeSet;

public class TreeSetDemo {

    public static void main(String[] args) {

        // 创建集合对象
// 自然顺序进行排序
TreeSet<Integer> treeSet = new TreeSet<Integer>(); // 创建元素并添加
// 3,6,9,12,15,18,21,22,30
treeSet.add(3);
treeSet.add(6);
treeSet.add(9);
treeSet.add(12);
treeSet.add(15);
treeSet.add(18);
treeSet.add(21);
treeSet.add(22);
treeSet.add(30); // 遍历结果
for (Integer data : treeSet) {
System.out.println("TreeSet --> "+data);
}
}
}

运行结果:

TreeSet --> 3
TreeSet --> 6
TreeSet --> 9
TreeSet --> 12
TreeSet --> 15
TreeSet --> 18
TreeSet --> 21
TreeSet --> 22
TreeSet --> 30

2.如果是引用数据类型来说,比如自定义对象,又该如何排序呢?

比如创建一个学生类:

package com.jia.set;

//学生类
public class Student { private Integer id;
private String name; public Student() {
} public Student(Integer id, String name) {
this.id = id;
this.name = name;
} public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}

测试类:

package com.jia.set;

import java.util.TreeSet;

public class StudentTreeSetDemo {

    public static void main(String[] args) {

        TreeSet<Student> treeSet = new TreeSet<Student>();
//创建元素对象
Student s1=new Student(1,"张三");
Student s2=new Student(2,"李四");
Student s3=new Student(3,"王五");
Student s4=new Student(4,"赵六");
Student s5=new Student(5,"陈七");
Student s6=new Student(6,"杨八"); //将元素对象添加到集合对象中
treeSet.add(s1);
treeSet.add(s2);
treeSet.add(s3);
treeSet.add(s4);
treeSet.add(s5);
treeSet.add(s6); //遍历结果
for (Student student : treeSet) {
System.out.println(student.getId()+"--->"+student.getName());
}
}
}

结果报错:

Exception in thread "main" java.lang.ClassCastException: com.jia.set.Student cannot be cast to java.lang.Comparable
at java.util.TreeMap.compare(TreeMap.java:1294)
at java.util.TreeMap.put(TreeMap.java:538)
at java.util.TreeSet.add(TreeSet.java:255)
at com.jia.set.StudentTreeSetDemo.main(StudentTreeSetDemo.java:20)
原因分析:
由于不知道该安照那一中排序方式排序,所以会报错。
解决方法:
1.自然排序
2.比较器排序

(1)自然排序

自然排序要进行一下操作:

1.Student类中实现Comparable接口

2.重写Comparable接口中的Comparable()方法

public int compareTo(T o); 比较此对象与指定对象的顺序。
package com.jia.set;

//学生类
public class Student implements Comparable<Student> { private Integer id;
private String name; public Student() {
} public Student(Integer id, String name) {
this.id = id;
this.name = name;
} public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
'}';
} @Override
public int compareTo(Student s) {
//return -1; //-1表示放在红黑树的左边,即逆序输出
//return 1; //1表示放在红黑树的右边,即顺序输出
//return o; //表示元素相同,仅存放第一个元素
//主要条件 姓名的长度,如果姓名长度小的就放在左子树,否则放在右子树
int num = this.name.length()-s.name.length();
//姓名的长度相同,不代表内容相同,如果按字典顺序此 String 对象位于参数字符串之前,则比较结果为一个负整数。
//如果按字典顺序此 String 对象位于参数字符串之后,则比较结果为一个正整数。
//如果这两个字符串相等,则结果为 0
int num1 = num==0?this.name.compareTo(s.name):num;
//姓名的长度和内容相同,不代表id值相同,所以还要判断id
int num2=num1==0?this.id-s.id:num1;
return num2;
}
}

运行结果:

1--->张三
2--->李四
6--->杨八
3--->王五
4--->赵六
5--->陈七

(2)比较器排序

步骤:1.单独创建一个比较类,以ComparatorTest为例,并且让其继承Comparator接口

   2.重写Comparable接口中的Comparable()方法

compare(T o1,T o2)      比较用来排序的两个参数。
TreeSet(Comparator<? superE> comparator)   构造一个新的空 TreeSet,它根据指定比较器进行排序。

创建比较类ComparatorTest:

package com.jia.set;

import java.util.Comparator;

public class ComparatorTest implements Comparator<Student> {

    @Override
public int compare(Student s1,Student s2) {
// 姓名长度
int num = s1.getName().length() - s2.getName().length();
// 姓名内容
int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
// id值
int num3 = num2 == 0 ? s1.getId() - s2.getId() : num2; return num3;
}
}

学生类:

package com.jia.set;

//学生类
public class Student { private Integer id;
private String name; public Student() {
super();
} public Student(Integer id, String name) {
this.id = id;
this.name = name;
} public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} }

测试类:

package com.jia.set;

import java.util.TreeSet;

public class StudentTreeSetDemo {

    public static void main(String[] args) {

        TreeSet<Student> treeSet = new TreeSet<Student>(new ComparatorTest());
//创建元素对象
Student s1=new Student(1,"张三");
Student s2=new Student(2,"李四");
Student s3=new Student(3,"王五");
Student s4=new Student(4,"赵六");
Student s5=new Student(5,"陈七");
Student s6=new Student(6,"杨八"); //将元素对象添加到集合对象中
treeSet.add(s1);
treeSet.add(s2);
treeSet.add(s3);
treeSet.add(s4);
treeSet.add(s5);
treeSet.add(s6); //遍历结果
for (Student student : treeSet) {
System.out.println(student.getId()+"--->"+student.getName());
}
}
}

运行结果:

1--->张三
2--->李四
6--->杨八
3--->王五
4--->赵六
5--->陈七

性能就不多讲了:HashSet > LinkedHashSet > TreeSet

最新文章

  1. 在windowService用Process.Start()启动程序没有界面-记录
  2. 【团队分享之二】IT团队绩效提升的一些见解
  3. Facebook内部高效工作PPT指南
  4. Android之桌面组件AppWidget
  5. ajaxfileupload踩过的坑
  6. JavaScript中url 传递参数(特殊字符)解决方法
  7. hdu 4550 贪婪 思考题 权
  8. 黑马程序猿_ 利用oc的协议实现代理模式
  9. websocket介绍
  10. Jenkins初识
  11. [UOJ UR #4追击圣诞老人]
  12. JAVA Web实时消息后台服务器推送技术---GoEasy
  13. selenium爬取煎蛋网
  14. springboot+springcloud集成jar
  15. python阅读目录
  16. Android Studio删除依赖
  17. u-boot(四)命令实现
  18. Mac安装Linux的KVM管理工具virt-manager
  19. SharePoint Excel Service - Couldn&#39;t Open the Workbook.
  20. C166-变量和函数指定物理地址之二

热门文章

  1. Linux 基础练习题
  2. 【第二十三期】春招实习阶段性总结(阿里云已OC)
  3. linux 运维工程师如何降低工作难度
  4. JAVA8学习——从使用角度深入Stream流(学习过程)
  5. 网页外部注入vConsole调试
  6. mysql学习+再复习
  7. [自动化]ansible-系统安全加固整改
  8. csaw密码
  9. 商业智能BI与用户行为分析的联系
  10. 2021年企业bi工具推荐