java基础——容器/集合类的概念及其使用

集合的概念

集合类又被称为容器,是java数据结构的实现,专门用来存储其他类的对象。常用的集合有List、Set、Map。其中List和Set继承了Collection接口。

KIMTOU

  • 说起集合,数组可是它的好兄弟,但是二者又有区别:
  1. 数组的长度是固定的,集合的长度是可变的。
  2. 数组用来存放基本类型的数据,集合用来存放对象的引用(即对象的地址)。
  3. 数组中只能是相同的数据类型,集合则可以存放不同的数据类型。


Collection接口

方法功能
add(Object obj)将指定对象添加到该集合中去
remove(Object obj)将指定对象从该集合中移除
isEmpty()返回boolean值,用于判断当前集合是否为空
size()返回int型值,获取改集合中的元素个数
contains(Object obj)返回boolean值,用于判断集合中是否存在该元素

以上是Collection接口的常用方法,由于List集合和Set集合继承了该接口,故这些方法对List和Set来说是通用的。

  • 测试
public class Test {
    public static void main(String[] args) {
        List list=new ArrayList();
        list.add(12);
        list.add("哈哈哈");
        list.add("冲冲冲");
        //打印list
        System.out.println(list);                   
        //获取集合元素个数
        System.out.println(list.size());             
        //移除指定元素
        list.remove("哈哈哈");                       
        //返回集合是否存在"哈哈哈"
        System.out.println(list.contains("哈哈哈"));  
    }
}
  • 运行结果
[12, 哈哈哈, 冲冲冲]
3
false


List集合

特点:元素允许重复,各元素的顺序就是对象插入的顺序

List与数组类似,可以使用索引访问元素。主要的实现类有ArrayList和LinkedList。

ArrayList

  • 底层:实现了可变的数组
  • 优点:可根据索引位置对集合进行快速的随机访问,查询速度快
  • 缺点:插入对象或删除对象的速度慢

LiskedList

  • 底层:采用链表结构保存对象
  • 优点:插入对象或删除对象的速度快,效率高
  • 缺点:查询速度慢,不便于访问

除了可以使用Collection接口的所有方法,List接口还定义了以下重要的方法

方法功能
get(int index)获取指定索引位置的元素
set(int index,Object obj)将集合指定索引位置的元素修改为指定对象
add(int index,Object obj)将指定对象插入到指定索引位置上
remove(int index)移除指定位置的元素
  • 测试
public class Test {
    public static void main(String[] args) {
        //创建泛型为String的List集合
        List<String> list = new ArrayList<>();
        list.add("你是谁");
        list.add("我又是谁");
        list.add("你好呀");
        //打印list
        System.out.println(list);                  
        //获取指定索引位置的元素
        System.out.println("索引位置为1的元素为:" + list.get(1));        
        //替换指定索引位置的元素
        list.set(1,"嘿嘿");                   
        System.out.println(list);
        //获取指定索引位置的元素
        System.out.println("索引位置为1的元素为:" + list.get(1)); 
        //添加元素到指定位置
        list.add(1,"我很好");       
        System.out.println(list);
    }
}
  • 运行结果
[你是谁, 我又是谁, 你好呀]
索引位置为1的元素为:我又是谁
[你是谁, 嘿嘿, 你好呀]
索引位置为1的元素为:嘿嘿
[你是谁, 我很好, 嘿嘿, 你好呀]


Set集合

特点:不能包含重复元素,不按特点方式排序

由于Set集合是无序且不重复的,故无法像List一样使用get,set,indexOf等有关元素具体位置的方法。

HashSet:

  • 底层:实现Set接口,由哈希表支持
  • 特点:不保证Set的迭代顺序

TreeSet:

  • 底层:不仅实现了Set接口,还实现了java.util.SortedSet接口
  • 特点:在遍历集合时按照自然顺序递增排序,也可以按照指定比较器递增排序


Map集合

Map集合没有继承Collection接口,其提供的是key到value的映射。Map中不允许包含相同的key(key不能重复,否则新的覆盖久的),且每个key只能映射一个value(value只能有一个,否则新的覆盖久的)。

  • Map接口中的常用方法
方法功能
put(K key,V value)向集合中添加指定的key和value的映射关系
get(Object key)如果存在指定的key对象,则返回该对象对应的值,否则返回null
keySet()返回该集合中所有key对象形成的Set集合
values()返回该集合所有值对象形成的Collection集合
containsKey(Object key)如果此映射包含指定key的映射关系,则返回true
containsValue(Object value)如果此映射将一个或多个key映射到指定值,则返回true

HashMap:

  • 底层:实现基于哈希表
  • 特点:通过哈希表对其内部的映射关系进行快速查找,但不保证映射的顺序

TreeMap:

  • 底层:不仅实现了Map接口,还实现了java.util.SortedMap接口
  • 特点:集合中的映射关系有一定的顺序,但在添加、删除、定位映射关系时,TreeMap类比HashMap的类的性能稍差
/**
 * Map常用操作
 */
public class testMap {
    public static void main(String args[]){
        //创建person对象
        person person1=new person(101,"cjt ",1.81);
        person person2=new person(102,"小伙子 ",1.79);
        //两种不同的Map
        Map<Integer,person> map1=new HashMap<>();
        Map<Integer,String> map2=new HashMap<>();
        //map1存入person对象
        map1.put(1,person1);
        map1.put(2,person2);
        //map2存入String对象
        map2.put(1,"cjt");
        //打印集合
        System.out.println(map1.get(1));
        System.out.println(map1);
        System.out.println(map2);
    }
}

/**
 * person实体类
 */
class person{
    int id;
    String name;
    double tall;

    public person(int id,String name,double tall){
        this.id=id;
        this.name=name;
        this.tall=tall;
    }

    @Override
    public String toString() {
        return "person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", tall=" + tall +
                '}';
    }
}

  • 运行结果
person{id=101, name='cjt ', tall=1.81}
{1=person{id=101, name='cjt ', tall=1.81}, 2=person{id=102, name='小伙子 ', tall=1.79}}
{1=cjt}


关于hashcode方法

hashcode的参考资料:https://www.cnblogs.com/qlqwjy/p/7731556.html

简介:hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用来在散列存储结构(如哈希表)中确定对象的存储地址的。凡是把类对象放到以哈希表为内部存储结构的容器中,相应的类必须要实现equals方法和hashCode方法,这样才符合哈希表真实的逻辑功能。

作用:hashcode方法返回对象的哈希码值,也就是对象的内存真实地址的整数化表示。如果两个对象内容相同,则对应的哈希码值也相同,尽管这些对象占用的是不同的内存。如果两个对象equals方法为true,则对应的hashcode值一定相等,因为equals就表示两对象相同。但是如果两对象hashcode值相等,则equals方法不一定为true。

为什么使用hashcode

考虑一种情况,当向集合中插入对象时,如何判别在集合中是否已经存在该对象了?(注意:集合中不允许重复的元素存在)
也许大多数人都会想到调用equals方法来逐个进行比较,这个方法确实可行。但是如果集合中已经存在一万条数据或者更多的数据,如果采用 equals方法去逐一比较,效率必然是一个问题。此时hashCode方法的作用就体现出来了,当集合要添加新的对象时,先调用这个对象的 hashCode方法,得到对应的hashcode值,实际上在HashMap的具体实现中会用一个table保存已经存进去的对象的hashcode 值,如果table中没有该hashcode值,它就可以直接存进去,不用再进行任何比较了;如果存在该hashcode值, 就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址,所以这里存在一个冲突解决的问题,这样一来实际调用 equals方法的次数就大大降低了,说通俗一点:Java中的hashCode方法就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的 字段等)映射成一个数值,这个数值称作为散列值。

简而言之:哈希表先判断是否有相同的hashcode值,如果没有,则直接存放进去。如果有,则根据它的hashcode方法提供的哈希码找到存储的位置,调用equals方法从位置所关联的链表里面寻找是否有相同的对象,如果有相同的对象,则不存放,如果没有,则存放进去。

注意事项:如果对象的equals方法被重写,那么对象的hashCode也尽量重写

应用场景:添加到Set集合的对象和添加到Map集合的键。



遍历容器

  • 方法一:使用for循环
public class TestList {
    public static void main(String args[]){
        ArrayList<String> list = new ArrayList<>();
        list.add("第一个");
        list.add("第二个");
        list.add("第三个");
        //使用for循环,通过索引遍历
        for(int i=0;i<list.size();i++){
            System.out.println(list.get(i));
            //同时也可通过索引删除元素
            //list.remove(i);
        }
        //增强for循环
        for(String str : list){
            System.out.println(str);
            //不能删除元素
        }
    }
}
public class Test {
    public static void main(String[] args) {
        Map<Integer,String> map = new HashMap<>();
        map.put(1,"第一个");
        map.put(2,"第二个");
        map.put(3,"第三个");
        //遍历键值
        for(int key : map.keySet()){
            System.out.println(key);
        }
        //遍历value
        for(String str : map.values()){
            System.out.println(str);
        }
        //同时获取key和value
        for(Map.Entry<Integer,String> entry : map.entrySet()){
            System.out.println("键:"+entry.getKey()+"值:"+entry.getValue());
        }
    }
}

  • 方法二:使用iterator迭代器遍历
public class TestList {
    public static void main(String args[]){
        ArrayList<String> list = new ArrayList<>();
        list.add("第一个");
        list.add("第二个");
        list.add("第三个");
        Iterator<String> it = list.iterator();
        //判断集合是否有下一个元素,返回boolean值
        while(it.hasNext()){
            //返回下一个元素并使游标后移一位
            String str = it.next();
            System.out.println(str);
        }
    }
}
public class Test {
    public static void main(String[] args) {
        Map<Integer,String> map = new HashMap<>();
        map.put(1,"第一个");
        map.put(2,"第二个");
        map.put(3,"第三个");
        //获取key集合
        Set<Integer> keySet = map.keySet();
        Iterator<Integer> it1 = keySet.iterator();
        while(it1.hasNext()){
            System.out.println(it1.next());
        }
        //获取value集合
        Collection<String> values = map.values();
        Iterator<String> it2 = values.iterator();
        while(it2.hasNext()){
            System.out.println(it2.next());
        }
        //获取键值对
        Iterator<Map.Entry<Integer,String>> entries = map.entrySet().iterator();
        while(entries.hasNext()){
            Map.Entry<Integer,String> entry = entries.next();
            System.out.println("键:"+entry.getKey()+"值:"+entry.getValue());
        }
    }
}

  • 方法三:使用lambda遍历
public class TestList {
    public static void main(String args[]){
        ArrayList<String> list = new ArrayList<>();
        list.add("第一个");
        list.add("第二个");
        list.add("第三个");
        list.forEach(s -> {
            System.out.println(s);
        });
    }
}
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值