Collection集合框架下的所有集合特点和用法

集合一:Collection接口下的所有集合

集合和数组的区别:

  • 数组特点:大小固定,只能存储相同数据类型的数据
  • 集合特点:大小可动态扩展,可以存储各种类型的数据,但只能是引用数据类型

Iterator接口被Collection接口继承, Collection的集合分别被List和set接口继承。

List接口和Set接口的区别:

  • 有序性: List保证按照插入顺序排序 ,Set 存储和取出的顺序不一致

  • 唯一性:List可重复,Set元素唯一

  • 获取元素:List可根据索引获取,Set无法根据索引获取

其实,有序或无序是指是否按照其添加的顺序来存储对象。List 是按照元素的添加顺序来存储的。而 Set 的实现类都有一套自己的排序算法,每添加一个元素,都会按照其内部算法将元素添加到合适的位置,所以不能保证内部存储是按元素添加的顺序而存储的。

List接口(有序且参数可重复)

List接口主要被:ArrayList、LinkedList、Vector类实现
(1)ArrayList:底层数据结构是数组,查询快,增删慢,线程不安全,效率高,可以存储重复元素
(2)LinkedList: 底层数据结构是链表,查询慢,增删快,线程不安全,效率高,可以存储重复元素
(3)Vector:底层数据结构是数组,查询快,增删慢,线程安全,效率低,可以存储重复元素

List集合常用的方法:

​ 1、add(Object element): 向列表的尾部添加指定的元素。
​ 2、size(): 返回列表中的元素个数。
​ 3、get(int index): 返回列表中指定位置的元素,index从0开始。
​ 4、add(int index, Object element): 在列表的指定位置插入指定元素。
​ 5、set(int i, Object element): 将索引i位置元素替换为元素element并返回被替换的元素。
​ 6、clear(): 从列表中移除所有元素。
​ 7、isEmpty(): 判断列表是否为空,不包含元素则返回 true,否则返回false。
​ 8、contains(Object o): 如果列表包含指定的元素,则返回 true。
​ 9、remove(int index): 移除列表中指定位置的元素,并返回被删元素。
​ 10、remove(Object o): 移除集合中第一次出现的指定元素,移除成功返回true,否则返回false。
​ 11、iterator(): 返回按适当顺序在列表的元素上进行迭代的迭代器。
​ 12、toArray(); 将集合转换成数组
​ 13、subList(int, int) 获取集合中某个范围的元素 //subList(0, 2)前2个元素
​ 14、lastIndexOf(object obj)获取集合中某个元素最后一次出现的索引

Set接口(无序且参数不可重复)

Set接口主要被HashSet、LinkedHashSet、TreeSet实现。

(1)HashSet:底层是哈希表实现的,存储顺序无序。可过滤重复的数据(需要在引用类型中重写hashCode和equals方法)。
(2)LinkedHashSet:底层哈希表加双向链表实现的,存储顺序有序。可过滤重复的数据(需要在引用类型中重写hashCode和equals方法)。
(3)TreeSet(自定义类型排序):数据结构采用二叉树来实现,元素唯一且已经排好序。自定义排序:具体实现看下面实现。

Person类:

public class Person {

    private String name;
    private  int age;
    private String version;

    public Person(String name, int age,String version) {
        this.name = name;
        this.age = age;
        this.version=version;
    }
    //去参数重复时要重写hashCode和equals
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Person)) return false;
        Person person = (Person) o;
        return getAge() == person.getAge() &&
                Objects.equals(getName(), person.getName());
    }
    @Override
    public int hashCode() {
        return Objects.hash(getName(), getAge(),getVersion());
    }
    
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", version='" + version + '\'' +
                '}';
    }
}

(1)HashSet底层数据结构采用哈希表实现,元素无序且唯一,线程不安全,效率高,可以存储null元素,元素的唯一性是靠所存储元素类型是否重写hashCode()和equals()方法来保证的,如果没有重写这两个方法,则无法保证元素的唯一性。

        //HashSet重写  hashCode和equals去重,他的存储是无序的
        HashSet<Object> i = new HashSet<>();
        i.add(new Person("小明",11,"0.0.1"));
        i.add(new Person("小明",12,"0.0.1"));
        i.add(new Person("小凯",11,"0.0.1"));
        i.add(new Person("小明",11,"0.0.1"));
        i.add(new Person("小明",11,"0.0.4"));
        for (Object o:i){
            System.out.println(o);
        }
        //输出:
//        Person{name='小明', age=12, version='0.0.1'}
//        Person{name='小明', age=11, version='0.0.4'}
//        Person{name='小明', age=11, version='0.0.1'}
//        Person{name='小凯', age=11, version='0.0.1'}

(2)LinkedHashSet底层数据结构采用链表和哈希表共同实现,链表保证了元素的顺序与存储顺序一致,哈希表保证了元素的唯一性。线程不安全,效率高。(比HashSet多了个保证存储顺序)

        //LinkedHashSet重写hashCode去重复,并且存储顺序是有序的
        LinkedHashSet<Object> linkedHashSet = new LinkedHashSet<>();
        linkedHashSet.add(new Person("小明",11,"0.0.1"));
        linkedHashSet.add(new Person("小凯",11,"0.0.1"));
        linkedHashSet.add(new Person("小明",12,"0.0.1"));
        linkedHashSet.add(new Person("小明",11,"0.0.4"));
        linkedHashSet.add(new Person("小明",11,"0.0.1"));
        linkedHashSet.add("dsaf4");
        for (Object o:linkedHashSet){
            System.out.println(o);
        }
        //输出:
        // Person{name='小明', age=11, version='0.0.1'}
        //Person{name='小凯', age=11, version='0.0.1'}
        //Person{name='小明', age=12, version='0.0.1'}
        //Person{name='小明', age=11, version='0.0.4'}
        //dsaf4

(3)TreeSet底层数据结构采用二叉树来实现,元素唯一且已经排好序;唯一性同样需要重写hashCode和equals()方法,二叉树结构保证了元素的有序性。根据构造方法不同,分为自然排序(无参构造)和比较器排序(有参构造);

  • 自然排序要求元素必须实现Compareable接口,并重写里面的compareTo()方法,元素通过比较返回的int值来判断排序序列, 返回0说明两个对象相同,不需要存储;

  • 比较器排需要在TreeSet初始化是时候传入一个实现Comparator接口的比较器对象,或者采用匿名内部类的方式new一个Comparator对象,重写里面的compare()方法;

1.自然排序

public class Person {
    
//需要在引用类型的数据中实现Compareable接口的compareTo(),实现排序
    private String name;
    private  int age;
    private String version;

    public Person(String name, int age,String version) {
        this.name = name;
        this.age = age;
        this.version=version;
    }

    //实现参数去重复
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Person)) return false;
        Person person = (Person) o;
        return getAge() == person.getAge() &&
                Objects.equals(getName(), person.getName());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getName(), getAge(),getVersion());
    }
    
    //自然排序(根据年龄重小到大排序)
    @Override
    public int compareTo(Person o) {
        //注意:Age重复情况下会数据会被过滤掉,参数比较是age
        return this.age-o.getAge();
    }  
}

自然排序实现:

  Set<Person> treeSet = new TreeSet<>();
  treeSet.add( new Person("张三", 12,"1.2.9.10"));
  treeSet.add(new Person("小孩", 14,"9.0"));
  treeSet.add(new Person("李四",18,"2.7.9.20"));
  treeSet.add(new Person("王五", 11,"9.0"));
  treeSet.add(new Person("小五", 11,"10.0"));
  for (Person p:treeSet){
      System.out.println(p);
  }
  //输出:因为age值排序中去重了,所以Person类小五被认为是重复的,不存入了集合
//Person{name='王五', age=11, version='9.0'}
//Person{name='张三', age=12, version='1.2.9.10'}
//Person{name='小孩', age=14, version='9.0'}
//Person{name='李四', age=18, version='2.7.9.20'}

2.比较器排序

方法一:使用匿名内部类

Set<Person> treeSet = new TreeSet<>(new Comparator<Person>() {
    @Override
    public int compare(Person o1, Person o2) {
        Person s1= (Person) o1;
        Person s2= (Person) o2;
        //现根据Version比较,version相等时在根据age比较
        int num2 =  s1.getVersion().compareTo(s2.getVersion()) ;
        // 次要条件 内容比较
        int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
        return num3;
    }
});
treeSet.add( new Person("张三", 12,"1.2.9.10"));
treeSet.add(new Person("小孩", 14,"9.0"));
treeSet.add(new Person("李四",18,"2.7.9.20"));
treeSet.add(new Person("王五", 11,"9.0"));
for (Person p:treeSet){
    System.out.println(p);
}

//输出:
//        Person{name='张三', age=12, version='1.2.9.10'}
//        Person{name='李四', age=18, version='2.7.9.20'}
//        Person{name='王五', age=11, version='9.0'}
//        Person{name='小孩', age=14, version='9.0'}

方法二:使用TreeSet的有参构造方法实现,传入实现Comparator接口compare方法的类

MycompareTo 实现 Comparator

public class MycompareTo implements Comparator {
    @Override
    public int compare(Object o1, Object o2) {
       Person s1= (Person) o1;
       Person s2= (Person) o2;
        if(s1.getVersion().compareTo(s2.getVersion()) >0){
            return 1;
        }else if (s1.getVersion().compareTo(s2.getVersion()) ==0){
           return s1.getAge() - s2.getAge();
        }else {
            return -1;
        }

    }
}

实现treeSet集合自定义排序:

Set<Person> treeSet = new TreeSet<>(new MycompareTo());
treeSet.add( new Person("张三", 12,"1.2.9.10"));
treeSet.add(new Person("小孩", 14,"9.0"));
treeSet.add(new Person("李四",18,"2.7.9.20"));
treeSet.add(new Person("王五", 11,"9.0"));
for (Person p:treeSet){
    System.out.println(p);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值