Java容器集合

本文深入探讨Java容器集合,包括Collection、List、Set接口的特点和使用。介绍泛型的作用,如数据安全和防止类型转换错误。讲解了集合工具类Collections的排序、复制等功能,以及自定义比较器Comparable和Comparator。最后讨论了包装类的自动装箱和拆箱机制,以及其在Integer缓存中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

容器集合

Java集合框架包含的内容

Java集合框架提供了一套性能优良、使用方便的接口和类,它们位于java.util包中

Collection是接口,一些Collection允许有重复(唯一)的元素,而另一些不允许(不唯一)。一些Collection是有序的(输入顺序与输出顺序相同),而另一些是无序的

Collection:存储的数据是不唯一、无序的对象

List:存储的数据是不唯一、有序的对象 Set:存储的数据是唯一、无序的对象

唯一:不能重复

有序:输入顺序是否与输出顺序是否一致

Collection:单值集合

集合常见方法:

addAll(): //可以将一个集合中的全部元素,增加到另一个集合之中
​
clear(): //清除集合中所有元素
​
contains(): //判断集合中是否包含了指定的对象或元素
​
containsAll(): //判断集合中是否包含指定集合的所有元素
​
isEmpty(): //判断集合是否为空
​
iterator(): //迭代器
​
removeAll(): //从一个集合中删除另一个集合所包含的所有元素
​
retainAll(): //两个集合中求交集

List中特有方法

indexOf(): //返回此列表中第一次出现的指定元素索引;如果没有此元素返回-1
​
lastIndexOf(): //返回此列表中最后出现的指定元素的索引,没有此元素返回-1
​
set(): //用指定元素替换列表中指定位置的元素
​
subList(): //截取List集合,左闭右开(按照元素索引来截取)

集合Map的使用

无序

key是唯一的,value是不唯一的

Map:“键值对”集合(key-value),kv一 一对应,可以根据key找到值

Map方法

put(): //加入key和value 
​
get(): //根据key找到value
​
containsKey(key): //判断是否包含了指定的key
​
containsValue(value): //判断是否包含了指定的value
//将Map转为单值集合
//转为只包含了Key的单值集合
Set set=map.keySet();
​
//转为只包含value的单值集合
Collection values =map.values();
​
//删除
remove(key);根据key删除value

删除:Collection和Map的区别

Collection中的类(List,Set),删除的返回值是boolean

Map中的类,是根据Key删除,返回值是value

如何遍历集合?list set map

1.for循环(普通for循环只适用于有序的集合,建议使用增强for)

2.迭代器(Iterator可用于无序)

//示例
Set set=new HashSet();
set.add("a");
set.add("b");
set.add("c");
/*
hasNext():判断是否存在下一个元素 true|false
如果有下一个元素,则引用后移
next(): 取得当前元素
*/
//迭代器遍历
Iterator iterator = set.iterator();
        while ( iterator.hasNext()){
            Object next = iterator.next();
            System.out.println(next);
        }

遍历map:将双值集合,转为单值集合

map-->keySet(取map的key集合)

map-->values(取map的values集合)

可以根据取出的key使用get方法来获取values

关于map的遍历

Map map=new HashMap();
        map.put("s01","张三");
        map.put("s02","李四");
        map.put("s03","王五");
        //将双值集合转换为单值集合
        Set set = map.keySet();
        //增强for循环
        for (Object k:set){
            System.out.print(k+"-");
            //根据key取values
            Object o = map.get(k);
            System.out.println(o);
        }
        //通过entry遍历
        //取出所有的entry
        Set entrys = map.entrySet();
        //遍历entry
        for (Object e:entrys){
            //强转,把e转为entry型
            Map.Entry e1 = (Map.Entry) e;
            //取key和value
            Object key = e1.getKey();
            Object value = e1.getValue();
            System.out.print(key+"-");
            System.out.println(value);
        }
​
//上述代码可以使用泛型:<类型>来进行限制,就不用进行强转

泛型

对于泛型类,Java编译器会将泛型代码转换为普通的非泛型代码,将类型参数T擦除,替换为Object,插入必要的强制类型转换。Java虚拟机实际执行的时候,它是不知道泛型这回事的,它只知道普通的类及代码。再强调一下,Java泛型是通过擦除实现的,类定义中的类型参数会被替换为Object,在程序运行过程中,不知道泛型的实际类型参数

作用:

1.数据安全

2.防止类型转换出错

集合工具类

集合工具类Collections:排序、复制、反转等操作

//查找元素在集合中的索引
//二分查法(使用前,必须保证集合元素是  自然有序的)
Collections.binarySearch(list,val);  //list:对象 val:元素
//打乱已有顺序
Collections.shuffle();
​
//调换两个指定索引位置上的元素  key:索引
Collections.swap(list,key1,key2);
​
//替换指定元素
Collections.replaceAll(list,oldVal,newVal);
​
//将集合所有元素替换为指定元素
Collections.fill(list,obj);

比较器

Collections.sort(list)://能够识别有序自然顺序

但是,如果集合中的元素是用户自定义对象,此方法就无法知道应该根据什么排序

根据这种情况Java提供了两个自定义比较器:Comparable和Comparator

Comparable:内部比较器(侵入性,要修改原有代码)

//测试类示例代码
package Exercise.Comparable;
​
import java.util.ArrayList;
import java.util.Collections;
​
public class ComparableTest {
    public static void main(String[] args) {
        ArrayList<Person> list=new ArrayList<>();
        //添加元素
        list.add(new Person(1,20,"张三",99));
        list.add(new Person(2,19,"王五",88));
        list.add(new Person(3,25,"赵迁",100));
        list.add(new Person(4,25,"李四",100));
​
        //已经实现了Comparable接口,所以可以直接使用sort方法排序
        Collections.sort(list);
        System.out.println(list);
        //在Person类中重写的方法是以年龄来进行升序排序
        //可以修改我们需要比较的元素来进行排序
    }
}
​
//Person类代码
package Exercise.Comparable;
​
public class Person implements Comparable{
        private int id;
        private int age;
        private String name;
        private int score;
​
        public Person() {}
​
        public Person(int id, int age, String name, int score) {
            this.id = id;
            this.age = age;
            this.name = name;
            this.score = score;
        }
​
        public int getId() {
            return id;
        }
​
        public void setId(int id) {
            this.id = id;
        }
​
        public int getAge() {
            return age;
        }
​
        public void setAge(int age) {
            this.age = age;
        }
​
        public String getName() {
            return name;
        }
​
        public void setName(String name) {
            this.name = name;
        }
​
        public int getScore() {
            return score;
        }
​
        public void setScore(int score) {
            this.score = score;
        }
​
        @Override
        public String toString() {
            return
                    " 学号=" + id +
                            " 年龄=" + age +
                            " 姓名='" + name  +
                            " 成绩=" + score+"\n";
        }
​
        @Override
        //实现了内部比较器,所以需要重写compareTo方法
        public int compareTo(Object o) {
            //返回1为降序
            //返回-1为升序
            //返回0为相等
            //进行强转
            int result;
           Person p=(Person) o;
            if (this.age>p.age){
                result=1;
            }else if (this.age==p.age){
                /*
                如果年龄相同,根据姓名排序,String类型已经重写了Comparable
                方法,直接调用即可(默认是升序)
                 */
                result=this.name.compareTo(p.name);
            }else {
                result=-1;
            }
            return result;
        }
}

思路:将比较的对象(Person)实现Comparable接口,重写compareTo方法,在compareTo中编写比较的逻辑

重点是返回值代表的顺序

Comparator:外部比较器(无侵入性,不影响原有代码)

1.先定义一个外部比较器

//定义外部比较器代码
package Exercise.Comparator;

import java.util.Comparator;

public class ComparatorWithID implements Comparator {
    @Override
    public int compare(Object o1, Object o2) {
        Student s1=(Student) o1;
        Student s2=(Student) o2;
        //int型返回相减的数就可以了
        return s1.getId()-s2.getId();
    }
}

2.在测试类中使用外部比较器

package Exercise.Comparator;


import java.util.ArrayList;
import java.util.Collections;

public class ComparatorTest {
    public static void main(String[] args) {
        ArrayList<Student> list =new ArrayList<>();

        //添加元素
        list.add(new Student(12,20,"张三",99));
        list.add(new Student(2,19,"王五",88));
        list.add(new Student(24,25,"赵迁",100));
        list.add(new Student(3,25,"李四",100));

        //指定使用外部比较器
        Collections.sort(list,new ComparatorWithID());
        System.out.println(list);
    }
}
//Student类
package Exercise.Comparator;

public class Student {
    private int id;
    private int age;
    private String name;
    private int score;

    public Student() {
    }

    public Student(int id, int age, String name, int score) {
        this.id = id;
        this.age = age;
        this.name = name;
        this.score = score;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return
                " 学号=" + id +
                        " 年龄=" + age +
                        " 姓名=" + name  +
                        " 成绩=" + score+"\n";
    }
}

包装类(自动装箱和自动拆箱)

Java语言是面向对象的编程语言,而基本数据类型声明的变量并不是对象,为了弥补这个概念,所以为其提供包装类,增强了Java面向对象的性质。

基本数据类型包装类
byteByte
shortShort
intInteger
longLong
booleanBoolean
charCharacter
floatFloat
doubleDouble

装箱:基本数据类型---->包装类(调用包装类的构造器)

Integer i=new Integer(123);
Integer i=new Integer("123");

Boolean b=new Boolean(true);
//注意:在Boolean包装类中,如果转换的不为true,那么无论输入什么,最后转换的一定是false

拆箱:包装类---->基本数据类型(调用包装类Xxx的xxxValue()方法)

Integer i=new Integer(12);
//包装类转换为基本数据类型
int i1=i.intValue();

Float f=new Float(12.1);
//包装类转换为基本数据类型
float=f.floatValue();

JDK 5.0新特性(自动装箱和自动拆箱)

//自动装箱
int num=10;
Integer num2=num;//直接将基本数据类型赋给包装类

//自动拆箱
int num3=num2;//将包装类直接赋给基本数据类型

注意:Integer内部定义了IntegerCache结构,此结构中定义了Integer[],保存了[-128,127]范围内的整数,如果我们使用自动装箱的方式,给Integer赋值的范围在-128到127范围内时,可以直接使用数组中的元素,超过这个范围就需要取new一个对象了

包装类、基本数据类型------>String类型(调用String重载的valueOf(Xxx xxx)方法)

int num=10;
//方式1:连接运算
String str1=num+"";

//方式2:用String的valueOf(Xxx  xxx)方法
Srting str2=String.valueof(num);

String类型------>包装类、基本数据类型(调用包装类内的parseXxx()方法)

//示例
String str1="123";
//进行转换
int num=Integer.parseInt(str1);

String str2="true";
//转换布尔
boolean b=Boolean.parseBoolean(str2);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值