集合

本文详细介绍了Java集合框架中Collection、List、Set接口及其重要子类(如ArrayList, HashSet, TreeSet)的功能、操作方法和区别,以及Map接口(包括HashMap, TreeMap)的键值对存储与查找。重点讲解了迭代器Iterator的使用和集合排序。

什么是集合

集合类是Java数据结构的实现。Java的集合类是java.util包中的重要内容,它允许以各种方式将元素分组,并定义了各种使这些元素更容易操作的方法。Java集合类是Java将一些基本的和使用频率极高的基础类进行封装和增强后再以一个类的形式提供。集合类是可以往里面保存多个对象的类,存放的是对象,不同的集合类有不同的功能和特点,适合不同的场合,用以解决一些实际问题。

Java 中的集合类库可以帮助我们在程序设计中实现传统的数据结构。

java类集结构图:

image-20210131221543634

Collection接口

Collection 接口是在整个 Java 类集中保存单值的最大操作父接口,里面每次操作的时候都只能保存一个对象的数据。 此接口定义在 java.util 包中。

接口的定义如下:

public interface Collection<E> extends Iterable<E>

此接口使用了泛型技术,在jdk1.5之后为了使类集操作得更加安全,所以引入了泛型。

List接口

该接口继承了Collection

public interface List<E> extends Collection<E>

是Collection的子接口

ArrayList类

该接口是List接口的子类

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

使用范例:

List<Integer> myList=new ArrayList<>();//实例化List对象
myList.add(0,1);//此方法调用的是List接口下的 0为下标
myList.add(2);//此方法可以从Collection接口调用也可从List调用
System.out.println(myList);//调用的是toString方法输出的

image-20210131224536199

可以发现,当在指定位置添加内容时的操作是List接口单独定义的

此时的对象数组并没有长度的限制,长度可以任意长,只要内存足够大

删除的方法为remove() ,可使用循环的方式输出,这里使用foreach循环遍历

List<Integer> myList=new ArrayList<>();//实例化List对象
myList.add(0,2);//此方法调用的是List接口下的
myList.add(1);
myList.remove(1);//1为下标
for (Integer b:myList){//此循环为foreach循环放入数组对象可方便的实现遍历操作
    System.out.println(b);
}
System.out.println(myList);//调用的是toString方法输出的

Vector类

Vector类也是List接口的子类。

定义如下:

public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable

vector类和ArrayList类的操作基本相同,这里不做过多的赘述

它们俩的区别如下图:

image-20210131230342362

Set接口

Set接口也是Collection的子接口,与List最大的不同是,Set接口里的内容都是不允许重复的。且与Collection接口基本上保持一致(没有进行进行扩充)

因为此接口中没有List接口中定义的get(int index)方法,所以无法使用循环输出

此接口中有两个常用的子类:HashSet,TreeSet

HashSet 散列存放

HashSet属于散列的存放类集,所以里面的内容是无序存放的

Set<String> mySet=new HashSet<>();
mySet.add("A");
mySet.add("B");
mySet.add("C");
mySet.add("D");
System.out.println(mySet);

使用 HashSet 实例化的 Set 接口实例,本身属于无序的存放。

虽然本身不可以循环输出,但是可以通过将集合变为对象数组进行输出,在Collection接口中就定义了这样的方法。

Set<String> mySet=new HashSet<>();
mySet.add("A");
mySet.add("B");
mySet.add("C");
mySet.add("D");
Object[] objects=mySet.toArray();
for(Object c:objects){
    System.out.println(c);
}

但是以上的操作不好,因为在操作的时候已经指定了操作的泛型类型,有更好的办法,就是由泛型所指定的类型变为指定的数组

Set<String> mySet=new HashSet<>();
mySet.add("A");
mySet.add("B");
mySet.add("C");
mySet.add("D");
String[] s=mySet.toArray(new String[]{});
for(String c:s){
    System.out.println(c);
}

TreeSet 排序的子类

与HashSet不同的是,TreeSet本身属于排序的子类

public class TreeSet<E> extends AbstractSet<E>
    implements NavigableSet<E>, Cloneable, java.io.Serializable

观察下面的代码:

Set<String> mySet2=new TreeSet<>();
mySet2.add("c");
mySet2.add("b");
mySet2.add("a");
System.out.println(mySet2);

image-20210201144716027

在添加元素时,虽然是无序的,但是在添加只有,却进行了排序。

排序说明

可以利用TreeSet的自动排序对对象进行排序,不过需要注意的是,该类需要实现comparable。

例如一个Person类:

class Person implements Comparable<Person>{
     private String name;
     private int age;
     private String sex;
    //重写compareTo方法,可对指定元素进行排序,这里对年龄进行排序
    @Override
    public int compareTo(Person o) {
        if (this.age > o.age) {
            return 1;
        } else if (this.age < o.age) {
            return -1;
        } else {
            return 0;
        }
    }
    @Override
    public String toString() {
        return "姓名='" + name + '\'' +
                ", 年龄=" + age +
                ", 性别='" + sex + '\'';
    }

    public Person(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        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 getSex() {
        return sex;
    }

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


}

测试:

public class Demo {
    public static void main(String[] args) throws IOException {
         Person person = new Person("张三", 20, "女");
        Person person1 = new Person("李四", 18, "男");
        Person person2 = new Person("老五", 21, "男");
        Set<Person> mySet2=new TreeSet<>();
        mySet2.add(person);
        mySet2.add(person1);
        mySet2.add(person2);
        System.out.println(mySet2);
    }    
 }

输出结果:

[姓名=‘李四’, 年龄=18, 性别=‘男’, 姓名=‘张三’, 年龄=20, 性别=‘女’, 姓名=‘老五’, 年龄=21, 性别=‘男’]

集合的输出

集合的输出最常用的是使用 Iterator(迭代器) 输出,这里只说明迭代器的使用。

Iterator(迭代器)

Iterator 属于迭代输出,基本的操作原理:是不断的判断是否有下一个元素,有的话,则直接输出。

public interface Iterator<E> {

要想使用此接口,则必须使用 Collection 接口,在 Collection 接口中规定了一个 iterator()方法,可以用于为 Iterator 接 口进行实例化操作。

public class Demo {
    public static void main(String[] args) throws IOException {
         Person person = new Person("张三", 20, "女");
        Person person1 = new Person("李四", 18, "男");
        Person person2 = new Person("老五", 21, "男");
        Set<Person> mySet2=new TreeSet<>();
        mySet2.add(person);
        mySet2.add(person1);
        mySet2.add(person2);
       Iterator<Person> iterator=mySet2.iterator();
        while (iterator.hasNext()){//判断是否有下一个元素
            System.out.println(iterator.next());输出当前的元素
        }
    }    
 }

输出结果:

姓名=‘李四’, 年龄=18, 性别=‘男’
姓名=‘张三’, 年龄=20, 性别=‘女’
姓名=‘老五’, 年龄=21, 性别=‘男’

但是在使用 Iterator 输出的时候有一点必须注意,在进行迭代输出的时候如果要想删除当前元素,则只能使用 Iterator 接口中的 remove()方法,而不能使用集合中的 remove()方法。否则将出现未知的错误。

Map接口

Map所储存的都是键值对,所谓键值对,键key就相当于一个数组的下标,但是相较于数组下标,键是可以自定义的。如:每一个学生都有对应的学号,而利用学号就可以查询出一个学生的信息,这个学生就是一个值。

public interface Map<K,V>

HashMap类

HashMap类是Map的子类,此类继承了 AbstractMap 类,同时可以被克隆,可以被序列化下来。

public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable

向集合中添加元素:

Map<Integer,Person> map=new HashMap<>();//<键,值>
Person person = new Person("张三", 20, "女");
Person person1 = new Person("李四", 18, "男");
Person person2 = new Person("老五", 21, "男");
map.put(1,person);
map.put(2,person1);
map.put(3,person2);
Person p=map.get(3);//通过键获取对象
System.out.println(p);

以上的操作是 Map 接口在开发中最基本的操作过程,根据指定的 key 找到内容,如果没有找到,则返回 null,找到了则返回具体的内容。

可以使用迭代,循环输出Map中的全部内容。

Map<Integer,Person> map=new HashMap<>();
Person person = new Person("张三", 20, "女");
Person person1 = new Person("李四", 18, "男");
Person person2 = new Person("老五", 21, "男");
map.put(1,person);
map.put(2,person1);
map.put(3,person2);
Set<Integer> set=map.keySet();//获取全部的键
Iterator<Integer> iterator=set.iterator();
while (iterator.hasNext()){
    System.out.println(map.get(iterator.next()));//通过键得到值再输出值
}

Hashtable类

这个类基本操作与 HashMap 是类似的,但是在Hashtable中是不能插入null的。

他们俩的区别:

image-20210201155010297

TreeMap

TreeMap 子类是允许 key 进行排序的操作子类,其本身在操作的时候将按照 key 进行排序,另外,key 中的内容可以 为任意的对象,但是要求对象所在的类必须实现 Comparable 接口。在使用 Map 接口的时候并不关心其是否排序,所以此类 只需要知道其特点即可。

总结

1、 类集就是一个动态的对象数组,可以向集合中加入任意多的内容。

2、 List 接口中是允许有重复元素的,Set 接口中是不允许有重复元素。

3、 List 接口的常用子类:ArrayList、Vector

4、 Set 接口的常用子类:HashSet、TreeSet

5、 TreeSet 是可以排序,一个类的对象依靠 Comparable 接口排序

6、 Map 接口中允许存放一对内容,key - value

7、 Map 接口的子类:HashMap、Hashtable、TreeMap

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值