Java集合框架

Chtholly 发布于 2022-08-25 1051 次阅读


Collection接口

public static void main(String[] args) {
        Collection collection = new ArrayList();

        //增
        collection.add("苹果");
        collection.add("西瓜");
        collection.add("菠萝");
        collection.add("榴莲");

        //删
        collection.remove("菠萝");
        //collection.clear();清空集合

        //遍历
        //增强for
        for(Object object : collection){
            System.out.println(object);
        }

        //迭代器
        Iterator iterator = collection.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

        //判断
        System.out.println(collection.contains("草莓"));//false
        System.out.println(collection.isEmpty());//false
    }

List接口

List集合的特点:有序、有下标、元素可以重复

public static void main(String[] args) {
        List list = new ArrayList();

        //增加
        list.add("苹果");
        list.add("小米");
        list.add(0,"华为");
        System.out.println(list);//[华为, 苹果, 小米]

        //删除
        //arrayList.remove(1);
        list.remove("苹果");
        list.add(20);
        //arrayList.remove((Object) 20);
        list.remove((new Integer(20)));

        //遍历
        //for
        for(int i=0;i<list.size();i++){
            System.out.println(list.get(i));
        }
        //增强for
        for(Object object : list){
            System.out.println(object);
        }
        //迭代器
        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        //列表迭代器 ListIterator可以向前或向后遍历、添加、删除、修改元素
        ListIterator listIterator = list.listIterator();
        //向后迭代
        while (listIterator.hasNext()){
            System.out.println(listIterator.nextIndex()+":"+listIterator.next());
            //0:华为
            //1:小米
        }
        //向前迭代
        while (listIterator.hasPrevious()){
            System.out.println(listIterator.previousIndex()+":"+listIterator.previous());
            //1:小米
            //0:华为
        }

        //sublist
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        System.out.println(list);//[华为, 小米, 1, 2, 3, 4, 5]
        System.out.println(list.subList(2,7));//[1, 2, 3, 4, 5]

    }

关于List的遍历删除,有一个关于foreach的坑

    @Test
    public void test1() {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        for(int num: list) {
            if (num == 2) {
                list.remove(num);
            }
        }
        System.out.println(StringUtils.join(list, ","));
    }

这样会报异常

java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
	at java.util.ArrayList$Itr.next(ArrayList.java:859)
	...

解决方案

    @Test
    public void test2() {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        List<Integer> tmp = new ArrayList<>();
        for(int num: list) {
            if (num == 2) {
                tmp.add(num);
            }
        }
        list.removeAll(tmp);
        System.out.println(StringUtils.join(list, ","));
    }

详情点击这里

List接口实现类

  • ArryList 数组结构实现,查询快,增删满。运行效率快,线程不安全
  • Vector 数组结构实现,查询快,增删慢。运行效率慢,线程安全
  • LinkedList 链表结构实现,增删快,查询慢

ArrayList

public static void main(String[] args) {
        ArrayList arrayList = new ArrayList();

        Student student1 = new Student("张三",18);
        Student student2 = new Student("李四",19);
        Student student3 = new Student("王五",20);
        Student student4 = new Student("赵六",21);

        //增
        arrayList.add(student1);
        arrayList.add(student2);
        arrayList.add(student3);
        arrayList.add(student4);
        System.out.println(arrayList);
        //[Student{name='张三', age=18}, Student{name='李四', age=19}, Student{name='王五', age=20}, Student{name='赵六', age=21}]

        //删
        arrayList.remove(student4);
        System.out.println(arrayList);//[Student{name='张三', age=18}, Student{name='李四', age=19}, Student{name='王五', age=20}]

        //遍历
        //for
        for (int i=0;i<arrayList.size();i++){
            System.out.println(arrayList.get(i));
        }
        //增强for
        for(Object object : arrayList){
            System.out.println(object);
        }
        //迭代器
        Iterator iterator = arrayList.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        //列表迭代器
        ListIterator listIterator = arrayList.listIterator();
        //正向迭代
        while (listIterator.hasNext()){
            System.out.println(listIterator.nextIndex()+":"+listIterator.next());
        }
        //逆向迭代
        while (listIterator.hasPrevious()){
            System.out.println(listIterator.previousIndex()+":"+listIterator.previous());
        }

        //判断
        System.out.println(arrayList.contains(student3));//true

        //查找
        System.out.println(arrayList.indexOf(student1));//0
    }

Vector与LinkedList

Vector和LinkedList的使用方法与ArrayList相同,不再演示

泛型

泛型中的<T>只能为引用类型(Integer)

泛型类

public class MyGeneric<T>{
    T t;

    //泛型作为方法的参数
    public void show(T t){
        System.out.println(t);
    }

    //泛型作为方法的返回值
    public T getT(){
        return t;
    }
}

泛型类的使用

public static void main(String[] args) {
        MyGeneric<String>  myGeneric = new MyGeneric<>();
        myGeneric.t = "Hello";
        myGeneric.show("world");//world
        System.out.println(myGeneric.getT());//Hello

        MyGeneric<Integer> myGeneric1 = new MyGeneric<>();
        myGeneric1.t = 100;
        myGeneric1.show(200);
        System.out.println(myGeneric1.getT());
    }

泛型类的接口

public interface MyInterface <T>{
    String name = "张三";

    T server(T t);
}

接口的实现类

//在实现类中确定类型
public class MyInterfaceImpl implements MyInterface<String >{
    @Override
    public String server(String s) {
        System.out.println(s);
        return null;
    }
}
//在实现类中使用泛型
public class MyInterfaceImpl2<T> implements MyInterface<T>{
    @Override
    public T server(T t) {
        System.out.println(t);
        return null;
    }
}

接口的使用

public static void main(String[] args) {

        MyInterfaceImpl myInterface = new MyInterfaceImpl();
        myInterface.server("你好");

        MyInterfaceImpl2 myInterfaceImpl2 = new MyInterfaceImpl2();
        myInterfaceImpl2.server("世界");

        MyInterfaceImpl2 myInterfaceImpl21 = new MyInterfaceImpl2();
        myInterfaceImpl21.server(404);

    }

泛型方法

public <T> void show(T t){
        System.out.println(t);
        //return t;
    }
    public static void main(String[] args) {
        Test06 test06 = new Test06();
        test06.show("Hello world");
    }

泛型集合

public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add("Hello");
        arrayList.add(" ");
        arrayList.add("World");
        System.out.println(arrayList);//[Hello,  , World]
    }

Set接口

Set集合的特点:无序、无下标、元素不可重复

public static void main(String[] args) {
        //创建集合
        Set<String> set = new HashSet<>();

        //增
        set.add("小米");
        set.add("华为");
        set.add("苹果");
        set.add("三星");
        System.out.println("数据个数:"+set.size()+" 集合内容"+set);//数据个数:4 集合内容[苹果, 华为, 小米, 三星]

        //删
        set.remove("三星");
        System.out.println(set);//[苹果, 华为, 小米]

        //遍历
        //增强for
        for(Object object : set){
            System.out.println(object);
        }
        //迭代器
        Iterator iterator = set.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

        //判断
        System.out.println(set.contains("华为"));

    }

Set接口实现类

  • HashSet(重点) 基于HashCode计算元素存放位置实现元素不重复
  • TreeSet 基于排列顺序实现元素不重复

HashSet

存储过程

(1)根据hashcode计算保存的位置,如果此位置为空,则直接保存,如果不为空执行第二步

(2)在执行equals方法,如果equals方法为true,则认为是重复,否则,形成链表

public static void main(String[] args) {
        HashSet<String> hashSet = new HashSet<>();
        hashSet.add("明");
        hashSet.add("日");
        hashSet.add("方");
        hashSet.add("舟");
        hashSet.add("终末地");
        System.out.println(hashSet);//[日, 终末地, 方, 明, 舟]

        hashSet.remove("终末地");
        System.out.println(hashSet);//[日, 方, 明, 舟]

        for (Object object : hashSet){
            System.out.println(object);
        }
        Iterator iterator = hashSet.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

        System.out.println(hashSet.contains("终末地"));
    }

TreeSet

特点:

  • 基于排列顺序实现元素不重复
  • 实现了SortedSet接口,对集合元素自动排序
  • 元素对象的类型必须实现Comparable接口,指定排序规则
  • 通过CompareTo方法确定是否为重复元素
public static void main(String[] args) {
        TreeSet<String> treeSet = new TreeSet<>();

        //增
        treeSet.add("abc");
        treeSet.add("xyz");
        treeSet.add("hello");
        treeSet.add("唐");
        System.out.println(treeSet.size()+" "+treeSet);//4 [abc, hello, xyz, 唐]

        //注意添加对象时需要实现compareTo方法
        TreeSet<Student> studentTreeSet = new TreeSet<>();
        Student student1 = new Student("张三",18);
        Student student2 = new Student("李四",19);
        Student student3 = new Student("王五",20);
        Student student4 = new Student("赵六",21);

        studentTreeSet.add(student1);
        studentTreeSet.add(student2);
        studentTreeSet.add(student3);
        studentTreeSet.add(student4);
        System.out.println(studentTreeSet);
        //[Student{name='张三', age=18}, Student{name='李四', age=19}, Student{name='王五', age=20}, Student{name='赵六', age=21}]

        //删
        treeSet.remove("xyz");
        System.out.println(treeSet);//[abc, hello, 唐]

        //遍历
        //增强for
        for (Object o : treeSet){
            System.out.println(o);
        }
        //迭代器
        Iterator<String> iterator = treeSet.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }

实现compareTo( )方法的Student类

public class Student implements Comparable<Student>{
    private String name;
    private int age;
    public Student(String name,int age){
        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 String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    @Override
    public int compareTo(Student o) {
        int n1 = this.getName().compareTo(o.getName());
        int n2 = this.getAge()-o.age;
        return n1==0?n2:n1;
    }
}

通过匿名内部类的Comparator接口实现比较器

public static void main(String[] args) {
        TreeSet<Student> studentTreeSet = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                int n1 = o1.getName().compareTo(o2.getName());
                int n2 = o1.getAge()-o2.getAge();
                return n1==0?n2:n1;
            }
        });

        Student student1 = new Student("张三",18);
        Student student2 = new Student("李四",19);
        Student student3 = new Student("王五",20);
        Student student4 = new Student("赵六",21);

        studentTreeSet.add(student1);
        studentTreeSet.add(student2);
        studentTreeSet.add(student3);
        studentTreeSet.add(student4);
        System.out.println(studentTreeSet);
        //[Student{name='张三', age=18}, Student{name='李四', age=19}, Student{name='王五', age=20}, Student{name='赵六', age=21}]
    }

Map接口

特点:

  • 用于存储任意键值对(Key-Value)
  • 键:无序、无下标、不允许重复(唯一)
  • 值:无序、无下标、允许重复
public static void main(String[] args) {
        Map<String , String> stringMap = new HashMap<>();

        stringMap.put("cn","中国");
        stringMap.put("us","美国");
        stringMap.put("uk","英国");
        stringMap.put("jp","日本");
        System.out.println(stringMap);//{uk=英国, jp=日本, cn=中国, us=美国}

        stringMap.remove("jp");
        System.out.println(stringMap);//{uk=英国, cn=中国, us=美国}

        //keySet
        /*Set<String> keySet = stringMap.keySet();
        for(String key : keySet){
            System.out.println(key+"="+stringMap.get(key));
        }*/
        for(String key : stringMap.keySet()){
            System.out.println(key+"="+stringMap.get(key));
        }
        //entrySet()方法 效率更高
        Set<Map.Entry<String,String>> entries = stringMap.entrySet();
        for(Map.Entry<String,String> entry: entries){
            System.out.println(entry);
        }
    }

Map接口实现类

  • HashMap 线程不安全,运行效率快;允许null作为key或value
  • Hashtable 线程安全,运行效率慢;不允许null作为key或value,实际几乎已被淘汰
  • Properties Hashtable的子类,要求key和value都为String,常用于配置文件的读取
  • TreeMap 实现了SortedMap接口,可以自动对key进行排序(用法参考TreeSet和HashMap)

HashMap

HashMap是依靠key的hashcode和equals方法来判断重复的,如果操作时new了一个新的对象,相当于开辟了新的空间,hashcode不同,HashMap不会认为是相同对象。如果需要判重,需要重写类中的hashcode和equals方法

public static void main(String[] args) {
        HashMap<Person,String> hashMap = new HashMap<>();

        Person person1 = new Person("猪八戒",1001);
        Person person2 = new Person("孙悟空",1002);
        Person person3 = new Person("沙和尚",1003);

        hashMap.put(person1,"上海");
        hashMap.put(person2,"北京");
        hashMap.put(person3,"上海");
        System.out.println(hashMap);
        //{Person{name='沙和尚', personNo=1003}=上海, Person{name='孙悟空', personNo=1002}=北京, Person{name='猪八戒', personNo=1001}=上海}

        //使用new添加相同name和personNo的对象时不会判重,需要重写hashcode和equals方法
        /*hashMap.put(new Person("猪八戒",1001),"上海");
        System.out.println(hashMap);*/
        //{Person{name='沙和尚', personNo=1003}=上海, Person{name='孙悟空', personNo=1002}=北京, Person{name='猪八戒', personNo=1001}=上海, Person{name='猪八戒', personNo=1001}=上海}

        //重写hashcode和equals方法后
        hashMap.put(new Person("猪八戒",1001),"上海");
        System.out.println(hashMap);
        //{Person{name='沙和尚', personNo=1003}=上海, Person{name='孙悟空', personNo=1002}=北京, Person{name='猪八戒', personNo=1001}=上海}
        //进行了判重,该对象没有添加进hashMap中

        //hashMap.remove(person1);
        //重写hashcode和equals方法之后可以使用该种方式删除
        hashMap.remove(new Person("猪八戒",1001));
        System.out.println(hashMap);

        //keySet
        Set<Person > keySet = hashMap.keySet();
        for(Person person : keySet){
            System.out.println(person+"="+hashMap.get(person));
        }
        //entry
        Set<Map.Entry<Person,String >> entries = hashMap.entrySet();
        for (Map.Entry entry : entries){
            System.out.println(entry);
        }

        System.out.println(hashMap.containsKey(person2));//true
        //重写hashcode和equals方法之后可以使用该种方式判断
        System.out.println(hashMap.containsKey(new Person("孙悟空",1002)));//true

    }

重写了hashcode和equals方法的Person类

public class Person {
    private String name;
    private int personNo;

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

    public String getName() {
        return name;
    }

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

    public int getPersonNo() {
        return personNo;
    }

    public void setPersonNo(int personNo) {
        this.personNo = personNo;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", personNo=" + personNo +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return personNo == person.personNo && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, personNo);
    }
}

Collections工具类

  • sort() 排序
  • binarySearch() 二分查找
  • copy() 复制
  • reserve() 反转
public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(10);
        list.add(21);
        list.add(4);
        list.add(9);
        list.add(17);

        //排序
        Collections.sort(list);
        System.out.println(list);//[4, 9, 10, 17, 21]

        //二分查找
        int index = Collections.binarySearch(list,9);
        System.out.println(index);//1

        //复制 要求两个集合大小相等
        List<Integer> list1 = new ArrayList<>();
        for (int i=0;i<list.size();i++){
            list1.add(0);
        }
        Collections.copy(list1,list);//[4, 9, 10, 17, 21]
        System.out.println(list1);

        //反转
        Collections.reverse(list);
        System.out.println(list);//[21, 17, 10, 9, 4]
    }

集合总结

  • 集合的概念:对象的容器,和数组类似,定义了对多个对象进行操作的常用方法。
  • List集合:有序、有下标、元素可以重复。(ArrayList、LinkedList、Vector)
  • Set集合:无序、无下标、元素不可重复。(HashSet、TreeSet)
  • Map集合:存储一对数据,无序、无下标、键不可重复、值可重复。(HashMap、TreeMap)
  • Collections:集合工具类,定义了除了存取以外的集合常用方法
此作者没有提供个人介绍。
最后更新于 2022-11-17