原创

Java集合知识点(一)

温馨提示:
本文最后更新于 2022年06月17日,已超过 9 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

java集合


在Java中存储一组数据的方式有集合和数组两种方式,那为什么我们要使用集合呢,首先来看一下数组和集合在存储数据方面上的特点

数组存储数据的特点

  • 数组在存储数据的时候事先就要申请好需要的存储长度,存储长度一旦申请好之后就无法被再一次修改
  • 定义数组的时候就要指明数组的类型,在之后的存储操作中不能往这个数组里面添加其他和定义时类型不一样的数据

数组存储数据的缺点

  • 一旦初始化之后长度就无法修改了
  • 数组中提供的方法非常有限,对于插入、删除数据非常不方便,效率也不高
  • 获取数组中实际元素的个数,数组没有线程的属性或者方法可以用
  • 数组存储数据是有序的,可重复的,对于不能重复,无序的需求数组不能满足

Java集合的种类和为什么要使用集合

  • 使用集合的主要目的就是为了解决数组中出现的问题
  • 在Java中集合分为两种体系:CollectionMap

集合框架

  • Collection接口:单列集合,存一个一个的对象,使用的时候并不是直接使用,而是使用Collection中的方法来实现集合的相关功能
    • List接口:存储有序的可重复的(动态数组)
      • ArrayList:作为List接口的主要实现类,是一个线程不安全的方法但是执行效率高,底层使用object数组来存储数据
        • 源码分析:jdk7和jdk8不同,在jdk7当中,ArrayList首先就创建了一个长度为10的数组,而jdk8之后起初没有创建,而是后面用到才进行创建,这样做了之后降低了内存的使用率
        • 建议开发中使用带参数的构造器,这样可以减少扩容的操作,避免每一次扩容copy一次,效率降低
      • Linkedlist:底层使用双向链表存储,对于频繁的插入,删除操作,效率比ArrayList效率高,因为是双向链表,在插入数据的时候就不用涉及到很多的数据(移位操作),而仅仅只涉及到相邻的连个数据的操作,从而大大提高了对数据的操作
        • 源码分析:一个数据分为三部分,头指针,数据,尾指针,主要涉及数据结
      • Vector:jdk1.0就有的实现类,线程安全的,执行效率低,底层使用object数组来存储,在开发中我们一般不使用
      • 三者的相同点
        • 都实现了list接口,存储数据的特点相同
    • Set接口:无序的不可重复的
      • HashsetLinkedhashsetTreeset
  • map接口:双列集合,存储一堆一堆的数据(key ——value)(高中函数:一对多,不能多对一)
    *hashmap(底层实现jdk7和jdk8不一样),linkedhashmaptreemaphashtableproperties

Collection接口中的方法

Collection接口中的方法

  1. add();往集合里面添加数据
 public void test1(){
   
Collection coll = new ArrayList();
coll.add(123);
}
  1. size();计算集合的元素个数
public void test1(){
   
Collection coll = new ArrayList();
coll.add(123);
System.out.println(coll.size());
}
  1. addAll();将一个集合中的元素添加到另一个集合当中
public void test1(){
   
Collection coll = new ArrayList();
coll.add(123);
Collection coll1 = new ArrayList();
        coll1.add(456);
        coll.addAll(coll1);
}
  1. clear();清理当前集合中的所有数据
coll.clear();
  1. isEmpty();判断当前集合是否为空值,如果为空就返回一个TRUE,否则就返回FALSE
System.out.println(coll.isEmpty());
  1. Contains();判断集合当中是否包含当前数据,没有则返回FALSE,否则返回TRUE
System.out.println(coll1.contains(456));
  1. ContainsAll();判断集合中是否包含另一个集合里面的数据…
System.out.println(coll1.containsAll(Arrays.asList(123, 4567)));
  1. remove();移除集合中的某一个数据
coll1.remove(123);
  1. removeAll();移除集合中的所有元素
 coll1.removeAll(coll2);
  1. retainAll();保留集合中和另一个集合中相同的元素(交集保留)
Collection coll2 = Arrays.asList(123, 456);
System.out.println(coll1.retainAll(coll2));
  1. hashCode();返回集合的hash值
System.out.println(coll1.hashCode());
  1. toArray();将集合转化为数组
Object[] arr = coll1.toArray();
  1. Arrays.asList();将数组转化为集合
List<String> strings = Arrays.asList(new String[]{
   "aa", "bb"});

iteration迭代器接口

Iteration迭代接口

  • Iterator对象称为迭代器接口,是一种设计模式,用来遍历集合中的数据
  • Iterator仅用于遍历集合数据,不提供承装对象的能力,如果需要创建Iterator接口,则必须有一个被迭代的集合
Iterator iterator = coll1.iterator();
while(iterator.hasNext()){
   
System.out.println(iterator.next());
}

hashNext和next都可以看做是一个指针,只不过hashNext是用来判断集合里面的数据是否为空,如果为空返回FALSE,否则返回TRUE,next是用来遍历集合里面的数据的

  • Iterator.remove();用来移除数据,这个方法移除数据的时候需要先判断数据是否存在
 Iterator iterator = coll1.iterator();
        while(iterator.hasNext()){
   
            Object obj = iterator.next();
            if("Tom".equals(obj)){
   
                iterator.remove();
            }

每一次判断相等的时候调用的都是equals方法,所以在我们需要进行比较两个数据是否一样的时候都需要重写equals方法,否则比较的将是两个数据的指针,这和我们的想法不同,就会导致出错

ForEach(增强for循环)

除了用迭代的方式遍历集合之外,遍历集合的方法还有增强for循环的方式,这种方式不仅仅可以用来遍历集合,还可以用来遍历数组,而且这种方法用来遍历时更简单

//for(集合当中元素的类型 局部变量 :集合对象/数组对象),虽然方法简单,但是内部任然调用迭代器
 for(Object obj : coll1){
   
            System.out.println(obj);
        }

Collection子接口一:List

ArrayList中的方法分析

  1. add();为集中插入数据,但是此时插入的数据可以进行角标选择,选择需要插入的位置
 list.add(1,"bb");
 //表示在角标为一的地方插入一个“bb”
  1. addAll();将一个集合插入到另一个集合中的固定位置处,此方法记录的角标是数据开始的第一个位置
list.addAll(1,integers);
//表示将集合integers插入到一的位置
  1. get();此方法将获取到角标处的值
 System.out.println(list.get(1));
 //表示获取到角标为一出的值
  1. indexOf();此方法判断数据是否存在,存在则返回角标位置,否则返回-1
int i = list.indexOf(123);
//表示判断123是否存在于集合当中
  1. lastIndexOf();此方法判断数据在集合中出现的最后一次位置
System.out.println(list.lastIndexOf(456));
//判断456在集合中出现的最后一次位置
  1. remove();此方法将指定角标的数据删除
Object remove = list.remove(0);
//表示将角标为0处的数据删除,并返回删除的数据
  1. subList();此方法返回角标为i-n的数据
List list1 = list.subList(1, 4);
//表示返回1-4之间的数据

在使用的时候没必要记住这么多的方法,主要记住增删改查方法就可以了

Collection子接口二:set

  • set都是使用Collection的方法,没有特别的方法
  • 存储数据时是无序的不可重复的
    • 无序说的不是数据打印出来的结果是无序的,而是在存储的时候存储在不同的地方,他们之间没有特定的数据,但是他们之间都通过指针连接,让他们输出的时候都可以按照输入的数据顺序输出
    • 通过数据的hash值决定存放的位置
    • 存放的数据是不可重复的,比较的时候依然使用equals,相同的元素只能添加一次
  • 为了保证向set中添加的数据不可重复性,其所在的类必须重写hashCOD和equals方法
  • hashset的底层是hashmap
  • LinkedHashSet作为hashset的子类,在添加数据的时候还创建了两个变量,记录了前一个数据和后一个数据,对于比较频繁的遍历操作比较方便。
  • treeset:向里面添加对象不能添加不同类的对象,只能添加某一个类的对象,可以按照类型的顺序进行排序
    • 如果是自定义类的话,需要指定排序的方式,排序分为自然排序,和定制排序(comparator):比较方法为compare

map接口

  • 用于存储双联数据
  • hashmap:作为map的主要实现类,是一个线程不安全的,效率高,存储null,key,value
    • linkedhashmap:加了一对指针,保证了遍历元素时,按照顺序进行遍历
  • treemap:底层使用红黑树
  • hashtable:作为古老的实现类,线程安全的
    • properties:用来处理配置文件
  • map的常用方法
    • put():向里面添加数据
    • puAall():将一个集合里面的数据添加到另一个集合
    • remove():移除key所对应的数据
    • get(Object key):通过指定key获取value
    • size(); 获取集合中元素的个数
    • clear(); 清空集合,元素个数清0
    • isEmpty(); 判断集合元素个数是否为0
    • containsKey(Object key); 判断集合中是否包含指定key
    • containsValue(Object value); 判断集合中是否包含指定value
    • keySet(); 获取集合中所有的key,返回一个包含所有key元素的Set集合
    • values(); 获取集合中所有的value,返回一个包含所有value元素的Collection集合
    • replace(K key, V oldValue, V newValue) 修改键值对<key, oldValue>的value为newValue

注意:contains()方法底层都调用了equals()方法,再次强调存入集合元素的类一定要重写equals()方法

正文到此结束