集合详解一、ArraryList和LinkedList

一、数组简介:

参考资料:https://blog.csdn.net/TTDreamTT/article/details/79000291

 

二、数组和集合的区别:

参考资料:https://blog.csdn.net/TTDreamTT/article/details/79000109
 

三、集合:

3.1、什么是集合?

存储对象的容器,面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作、存储对象,集合是存储对象最常用的一种方式。

集合的出现就是为了持有对象。集合中可以存储任意类型的对象,而且长度可变。在程序中有可能无法预先知道需要多少个对象,那么用数组来装对象的话,长度不好定义(数组长度是固定的),而集合解决了这样的问题。

集合类主要负责保存、盛装其他数据,因此集合类也被称为容器类。所以的集合类都位于java.util包下,后来为了处理多线程环境下的并发安全问题,java5还在java.util.concurrent包下提供了一些多线程支持的集合类。
 

3.2、集合的架构图

在这里插入图片描述

  • Collection接口是集合类的根接口,Java中没有提供这个接口的直接的实现类。但是却让其被继承产生了两个接口,就是Set和List。Set中不能包含重复的元素。List是一个有序的集合,可以包含重复的元素,提供了按索引访问的方式。
  • Map是Java.util包中的另一个接口,它和Collection接口没有关系,是相互独立的,但是都属于集合类的一部分。Map包含了key-value对。Map不能包含重复的key,但是可以包含相同的value。
  • Iterator,所有的集合类,都实现了Iterator接口,这是一个用于遍历集合中元素的接口,主要包含以下三种方法:
    1、hasNext()是否还有下一个元素。
    2、next()返回下一个元素。
    3、remove()删除当前元素。

 

3.3、Collection集合的方法:

Collection是最基本的集合接口,一个Collection代表一组Object的集合,这些Object被称作Collection的元素。Collection是一个接口,用以提供规范定义,不能被实例化使用。
在这里插入图片描述
 

3.3.1、Collection集合的方法:

  1. 添加方法:
    boolean add(Object obj); --添加;
    boolean addAll(Collection coll) --添加集合;
  2. 删除方法:
    boolean remove(Ooject obj); --删除;
    boolean remove(Collection coll) --删除集合;
    void clear() --移除所有内容。
  3. 获取方法:
    int size(); --返回集合中的元素数;
    Iterator iterator(); --取出元素的方式:迭代器。
  4. 判断方法:
    boolean contains(object obj); --判断些集合指定的元素,则返回true;
    boolean containsAll(Collection coll) --判断两个集合的元素是否一样,是返回true;
    boolean isEmpty(): --判断集合中是否有元素。
  5. 其他方法:
    boolean retainAll(Collection coll) --两个集合元素都一致,返回false,否则返回true
    Object[] toArray(): --将集合转成数组。
/**
 * Collection集合的方法详解
 */
public class CollectionTest {
    public static void main(String[] args) {
        Collection col1 = new ArrayList();
        //show(col1);

        Collection col2 = new ArrayList();
        Collection col3 = new ArrayList();
        show(col2,col3);
    }

    public static void show(Collection col1){
        //新增
        col1.add("123");
        col1.add("木头人");
        col1.add("汐");
        System.out.println("输出所有元素:"+col1);
        System.out.println("获取集合元素个数:"+col1.size());
        System.out.println("判断该集合是否包含“123”元素:"+col1.contains("123"));//包含返回true
        System.out.println("判断该集合是有元素:"+col1.isEmpty());//没有返回true


    }


    public static void show(Collection col2,Collection col3){
        Collection col4=new ArrayList();

        //新增
        col2.add("123");
        col2.add("木头人");
        col2.add("汐");


        col3.add("123");
        col3.add("木头人");
        col3.add("喜");

        col4.addAll(col2);
        col4.addAll(col3);

        System.out.println("将col2、col3集合添加到cole集合中:"+col4);
        System.out.println("判断col2集合中包含col3集合的所有元素,没有则返回false:"+col2.containsAll(col3));
        System.out.println("两个集合元素一致返回false:"+col2.retainAll(col3));
    }
}

 

3.4、常用集合的分类::

在这里插入图片描述

 

四、List集合:

List是Collection的子接口,List集合代表一个元素有序、可重复的集合,集合中每个元素都有其对应的顺序索引。List集合允许加入重复元素,因为它可以通过索引来访问指定位置的集合元素。List集合默认按元素的添加顺序设置元素的索引。
 

4.1、list集合特性:

  • 有序性:list保证插入元素按照顺序,尾部插入元素;

  • 唯一性:list集合中的元素可以重复;

  • 获取元素:list集合可以通过索引获取元素。
    在这里插入图片描述

  • ArrayList:底层数据结构是数组,查询快,增删慢,线程不安全,效率高,可以存储重复元素。

  • LinkedList 底层数据结构是链表,查询慢,增删快,线程不安全,效率高,可以存储重复元素。

  • Vector:底层数据结构是数组,查询快,增删慢,线程安全,效率低,可以存储重复元素

 

4.2、ArrayList集合:

 

4.2.1、ArrayList 集合简介

ArrayList 是 java 集合框架中比较常用的数据结构了。继承自 AbstractList,实现了 List 接口。底层基于数组实现容量大小动态变化。
允许 null 的存在。同时还实现了 RandomAccess、Cloneable、Serializable 接口,所以ArrayList 是支持快速访问、复制、序列化的

 

4.2.2、ArrayList 常用方法:

在这里插入图片描述
 

4.2.3、ArrayList 底层代码分析:

ArrayList源码分析:https://blog.csdn.net/TTDreamTT/article/details/111477220
 

4.2.4、ArrayList 遍历方式:

ArrayList遍历方式主要有以下几种方式:

/**
 * ArraryList的遍历方式
 */
public class ArrayListTest {
    public static void main(String[] args) {

    List<String> list=new ArrayList<>();
        list.add("123");
        list.add("456");
        list.add("789");

        //方式一、使用for循环的方式
        for (int i = 0; i < list.size(); i++) {
            //System.out.println(list.get(i));
        }

        //方式二、使用foreach方式
        for (String s : list) {
            //System.out.println(s);
        }

       //方式三、使用Iterator迭代器方式
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}

 

4.2.5、ArrayList 排序方式:

 

1、方式一:使用Collections.sort()排序:

对任意类型的集合对象,进行整体排序,排序时将此接口的实现传递给Collections.sort方法排序;实现int compare(T o1, T o2);方法,返回正数,零,负数各代表大于,等于,小于。

sort方法:

  • void sort(List list),按自然排序的升序排序;
  • void sort(List list, Comparator c);定制排序,由Comparator控制排序逻辑。

 
自然排序和定制排序:

/**
     * ArraryList的排序方式:自然排序
     *  1、当list集合的类型不是pojo对象类型的时候,可以按自然排序-升序排序;
     *  2、当list集合的类型是pojo对象类型的时候,不能使用自然排序,使用定制排序,由Comparator控制排序逻辑;
     */
    private static void test5(){
        List<String > list1  = new ArrayList();
        list1.add("4");
        list1.add("2");
        list1.add("34");
        list1.add("43");
        list1.add("55");

        List<Integer> list2  = new ArrayList();
        list2.add(4);
        list2.add(2);
        list2.add(34);
        list2.add(43);
        list2.add(55);

        List<Student> list3  = new ArrayList();
        Student s1 = new Student();
        Student s2 = new Student();
        Student s3 = new Student();

        s1.setAge(1);
        s2.setAge(7);
        s3.setAge(3);

        list3.add(s1);
        list3.add(s2);
        list3.add(s3);

        Collections.sort(list1);
        Collections.sort(list2);

        Collections.sort(list3, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return 0;
            }
        });
    }

 
单一条件排序:

 /**
     * ArraryList的排序方式:单一条件排序
     */
    private static void test2(){
        List<Student> list1=new ArrayList<>();
        Student s1=new Student();
        Student s2=new Student();
        Student s3=new Student();

        s1.setId("1");
        s1.setName("张三");
        s1.setAge(30);

        s2.setId("2");
        s2.setName("李四");
        s2.setAge(20);

        s3.setId("3");
        s3.setName("王五");
        s3.setAge(60);

        list1.add(s1);
        list1.add(s2);
        list1.add(s3);

        System.out.println("排序前:::"+list1);
        //对users按年龄进行排序
        Collections.sort(list1, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                //升序排序
                //return o1.getAge()-o2.getAge();
                //return o1.getAge().compareTo(o2.getAge());

                //降序排序
                //return o2.getAge()-o1.getAge();
                return o2.getAge().compareTo(o1.getAge());
            }
        });

        System.out.println("排序后:::"+list1);
    }

 
 
多条件排序:

/**
     * ArraryList的排序方式:多条件排序
     */
    private static void test3(){
        List<Student> list2=new ArrayList<>();
        Student s1=new Student();
        Student s2=new Student();
        Student s3=new Student();
        Student s4=new Student();
        Student s5=new Student();
        Student s6=new Student();

        s1.setAge(30);
        s2.setAge(20);
        s3.setAge(40);
        s4.setAge(30);
        s5.setAge(40);
        s6.setAge(20);

        s1.setNum(1);
        s2.setNum(2);
        s3.setNum(3);
        s4.setNum(4);
        s5.setNum(5);
        s6.setNum(6);

        s1.setName("张三");
        s2.setName("李四");
        s3.setName("王五");
        s4.setName("赵六");
        s5.setName("陈七");
        s6.setName("周八");

        list2.add(s1);
        list2.add(s2);
        list2.add(s3);
        list2.add(s4);
        list2.add(s5);
        list2.add(s6);

        System.out.println("排序前:::"+list2);
        //对users按年龄进行排序
        Collections.sort(list2, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                int flag;
                //首先按照年龄升序排序
                flag=o1.getAge()-o2.getAge();
                if (flag ==0){
                    // 再按学号升序排序
                    flag=o1.getNum()-o2.getNum();
                }
                return flag;
            }
        });

        System.out.println("排序后=========");
        System.out.println("年龄   学号    姓名");
        for(Student s : list2){
            System.out.println(s.getAge()+"     "+s.getNum()+"     "+s.getName());
        }
    }

 
 
自定义条件排序:

 /**
     * ArraryList的排序方式:自定义条件排序
     */
    private static void test4(){
        //定义数组:排序规则,按照该数组的规则排序
        String[] order={"语文","数学","英语","物理","化学","生物","政治","历史","地理","总分"};
        //将数组转换为list
        final List<String> defiderOrder  = Arrays.asList(order);
        List<String> list = new ArrayList<>();
        list.add("总分");
        list.add("英语");
        list.add("政治");
        list.add("总分");
        list.add("数学");
        System.out.println("排序前::"+list);

        Collections.sort(list, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                int io1=defiderOrder.indexOf(o1);
                int io2=defiderOrder.indexOf(o2);
                return io1-io2;
            }
        });

        System.out.println("排序后============");
        for (String s : list) {
            System.out.println(s+"   ");
        }
    }

 

2、方式二:使用list.sort()排序:
	/**
     *  ArraryList的排序方式:使用list.sort()方法排序
     */

    private static void test6(){
        List<Integer> list=new ArrayList<>();
        list.add(4);
        list.add(2);
        list.add(34);
        list.add(43);
        list.add(55);

        System.out.println("排序前:::"+list);
        list.sort(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                //升序排序
                return o1.compareTo(o2);
            }
        });

        System.out.println("排序后:::"+list);
    }


	/**
     *  ArraryList的排序方式:使用list.sort()方法排序
     */
	private static void test6(){
        List<String> list=new ArrayList<>();
        list.add("4");
        list.add("2");
        list.add("34");
        list.add("43");
        list.add("55");

        System.out.println("排序前:::"+list);
        list.sort(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                //升序排序
                return o1.compareTo(o2);
            }
        });
    }

切记

  • 对于List类型的集合,排序的结果是按照大小拍的,没问题;
  • 对于List类型的集合,排序的结果是自然排序的,如上面实例:结果为:
    [2, 34, 4, 43, 55],显然这种顺序不是我们想要的,那么这种只能使用自定义排序。
  • 自然顺序排序和自然顺序降序这两个方法用来对集合中的元素是基本类型String类型进行排序;如果直接将对象(pojo)进行排序,会没有效果,即使你将对象实现了Comparable接口,也没有任何效果。
  • 所以,List对象类型的集合排序要使用:Collections.sort()排序。

 

4.2.6、ArrayList 去重:

 

1、方式一:set集合去重,不改变原有的顺序:
/**
     * 方式一:set集合去重,不改变原有的顺序
     */
    private static void test1(){

        List<String> listNew=new ArrayList<>();
        List<String> list=new ArrayList<>();
        list.add("aa");
        list.add("bb");
        list.add("cc");
        list.add("aa");
        list.add("dd");
        list.add("bb");

        Set<Object> set = new HashSet<>();

        for (String s : list) {
            if(set.add(s)){
                listNew.add(s);
            }
        }
        System.out.println(set);
    }

 

2、方式二:set集合去重:
/**
     * 方式二:set集合去重
     */
    private static void test1(){

        List<String> listNew=new ArrayList<>();
        List<String> list=new ArrayList<>();
        list.add("aa");
        list.add("bb");
        list.add("cc");
        list.add("aa");
        list.add("dd");
        list.add("bb");

        Set<Object> set = new HashSet<>();
        set.addAll(list);
        System.out.println(set);
    }

 

3、方式三:遍历后判断赋给另一个list集合:
/**
     * 方式三:遍历后判断赋给另一个list集合
     */

    private  static void test2(){
        List<String> listNew=new ArrayList<>();
        List<String> list=new ArrayList<>();
        list.add("aa");
        list.add("bb");
        list.add("cc");
        list.add("aa");
        list.add("dd");
        list.add("bb");

        for (String s : list) {
            if (!listNew.contains(s)){
                listNew.add(s);
            }
        }
        System.out.println("去重后:::"+listNew);
    }

 

4、方式四:去重并按自然顺序排序:
/**
     * 方式四:去重并按自然顺序排序
     */

    private  static void test4(){
        List<String> list=new ArrayList<>();
        list.add("aa");
        list.add("bb");
        list.add("cc");
        list.add("aa");
        list.add("dd");
        list.add("bb");

        List<String> listNew = new ArrayList<>(new TreeSet<String>(list));
        System.out.println("去重后:::"+listNew);
    }

 

5、方式五:set和list转换去重:
/**
     * 方式五:set和list转换去重
     */

    private  static void test5(){
        List<String> list=new ArrayList<>();
        list.add("aa");
        list.add("bb");
        list.add("cc");
        list.add("aa");
        list.add("dd");
        list.add("bb");

        Set set=new HashSet();
        List<String> listNew = new ArrayList<>();

        set.addAll(list);
        listNew.addAll(set);
        System.out.println("去重后:::"+listNew);
    }

 

6、方式六:双重for循环去重(不建议使用,效率太慢):
 /**
     * 方式六:双重for循环去重-不建议使用,效率太慢
     */
    private  static void test6(){
        List<String> list=new ArrayList<>();
        list.add("aa");
        list.add("bb");
        list.add("cc");
        list.add("aa");
        list.add("dd");
        list.add("bb");
        
        for (int i = 0; i < list.size(); i++) {
            for (int j = list.size()-1; j >i ; j--) {
                if (list.get(j).equals(list.get(i))){
                    list.remove(j);
                }
            }
        }
        System.out.println("去重后:::"+list);
    }

 
 

4.2.7、常见问题:

1.问题描述

在使用ArrayList比较常见的一个问题就是在遍历ArrayList的时候调用remove()方法进行元素的删除操作,从而得到意想不到的结果,本人在开发过程中也遇到过这样的问题,所以在这里提出了,希望能够帮助到大家。

2.实例及分析
如下代码中,在遍历List时,调用了remove方法,删除元素a

//arrayList中的值为 [a,a,c,a,a]
for (int i = 0; i < arrayList.size(); i++) {
    if (arrayList.get(i) == "a") {
        arrayList.remove(i);
    }
}
System.out.println(arrayList);

这段代码看似解决了删除列表中所有的a元素,但是删除后得出List的结果为[a, c, a],为什么这种方式没有达到想要的效果,其实仔细分析后会发现,在调用remove()方法时List的长度会发生变化而且元素的位置会发生移动,从而在遍历时list实际上是变化的;
例如:
当i=0时,此时list中的元素为[a,a,c,a,a],
但当i=1时,此时List中的元素为[a,c,a,a],元素的位置发生了移动,从而导致在遍历的过程中不能达到删除的效果。

3.解决方案:使用迭代器中的remove方法
通过上述的分析可以看出,出现问题的原因是元素的位置发生了移动,从而导致异常的结果。

Iterator<String> ite = arrayList.listIterator();
while (ite.hasNext()){
    if(ite.next() == "a")
        ite.remove();
}
System.out.println(arrayList);

 
 

4.2.8、取List中的前几条数据:

// start,end分别是第几个到第几个,strat和end为索引,从0开始
list = list.subList(start, end); 

 
 

4.2.9、ArrayList在JDK1.8中的新特性:

 
详解:https://blog.csdn.net/TTDreamTT/article/details/111629276

 
 
 
 

4.3、LinkedList:

 

4.3.1、简介:

  • 链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。

  • 链表可分为单向链表和双向链表:
    一个单向链表包含两个值: 当前节点的值和一个指向下一个节点的链接。

  • Java LinkedList(链表) 类似于 ArrayList,是一种常用的数据容器。
    与 ArrayList 相比,LinkedList 的增加和删除对操作效率更高,而查找和修改的操作效率较低。
     

4.3.2、使用场景:

以下情况使用 ArrayList :

  • 频繁访问列表中的某一个元素。
  • 只需要在列表末尾进行添加和删除元素操作。
     

以下情况使用 LinkedList :

  • 你需要通过循环迭代来访问列表中的某些元素。
  • 需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。


public class LinkedListTest {
    public static void main(String[] args) {
       // test1();
        test2();

    }
    /**
     * 在首、尾部操作元素
     */
    private static void test2(){
        LinkedList<String> linkedList = new LinkedList<>();
        linkedList.add("Google");
        linkedList.add("Runoob");
        linkedList.add("Taobao");
        linkedList.addLast("Wiki");//在尾部添加元素
        linkedList.removeLast();//移除尾部元素
        linkedList.addFirst("first");//在头部添加元素
        linkedList.removeFirst();//移除头部元素
        System.out.println(linkedList);
        System.out.println(linkedList.getFirst());//获取开头元素
        System.out.println(linkedList.getLast());//获取尾部元素
    }

    /**
     * 添加元素
     */
    private static void test1(){
        LinkedList<String> linkedList = new LinkedList<>();
        linkedList.add("Google");
        linkedList.add("Runoob");
        linkedList.add("Taobao");
        linkedList.add("Weibo");
        System.out.println(linkedList);
    }
}

 

4.3.3、层级结构:

  • LinkedList 继承了 AbstractSequentialList 类。
  • LinkedList 实现了 Queue 接口,可作为队列使用。
  • LinkedList 实现了 List 接口,可进行列表的相关操作。
  • LinkedList 实现了 Deque 接口,可作为队列使用。
  • LinkedList 实现了 Cloneable 接口,可实现克隆。
  • LinkedList 实现了 java.io.Serializable 接口,即可支持序列化,能通过序列化去传输。

在这里插入图片描述

 

4.3.4、LinkedList的使用:

 

1、创建LinkedList:
LinkedList<E> list = new LinkedList<E>();   // 普通创建方法

或者
LinkedList<E> list = new LinkedList(Collection<? extends E> c); // 使用集合创建链表

 

2、创建一个简单的链表实例:
public class LinkedListTest {

    public static void main(String[] args) {

        LinkedList<String> linkedList = new LinkedList<>();
        linkedList.add("Google");
        linkedList.add("Runoob");
        linkedList.add("Taobao");
        linkedList.add("Weibo");
        System.out.println(linkedList);
    }
}

 

3、LinkedList 遍历方式:
	/**
     * 遍历-循环
     */
    private static void test3(){
        LinkedList<String> linkedList = new LinkedList<>();
        linkedList.add("Google");
        linkedList.add("Runoob");
        linkedList.add("Taobao");
        linkedList.add("Weibo");

        //方式一:普通for循环
        for (int i = 0; i < linkedList.size(); i++) {
           // System.out.println(linkedList.get(i));
        }

        //方式二:foreach 循环
        for (String s : linkedList) {
            //System.out.println(s);
        }

        //方式三:使用迭代器 iterator
        Iterator<String> iterator = linkedList.iterator();
        while (iterator.hasNext()){
            //System.out.println(iterator.next());
        }

        //方式四:用pollFirst()来遍历LinkedList
        while (linkedList.pollFirst() !=null);

        //方式五:pollLast()来遍历LinkedList
        while(linkedList.pollLast() != null);

        //方式六:removeFirst()来遍历LinkedList
        while(linkedList.removeFirst() != null) ;

        //方式七:removeLast()来遍历LinkedList
        while(linkedList.removeLast() != null);
    }

由此可见,遍历LinkedList时,使用removeFist()或removeLast()效率最高。但用它们遍历时,会删除原始数据;若单纯只读取,而不删除,LinkedList遍历时建议使用For-each或者迭代器的方式。千万不要通过随机访问去遍历LinkedList!

 

4.3.5、常用方法:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

 

4.3.6、LinkedList底层解析:

LinkedList源码分析:
https://blog.csdn.net/TTDreamTT/article/details/111561830

 

4.3.7、LinkedList排序:

 
 
 

致谢:

参考:https://www.jianshu.com/p/92373a603d42
参考:https://blog.csdn.net/sihai12345/article/details/79382649
参考:https://blog.csdn.net/lx_nhs/article/details/78871295

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值