集合的使用

在这里插入图片描述

集合框架

**概念:**集合是一种对象容器,用于存放对象
数组的缺点:
1.定长,一旦定义就不能被改变
2.数组中没有方法
3.只能存放相同的数据类型
集合的特点:
1.长度可以变化
2.有丰富的操作方法
3.集合只能存放引用数据类型
集合的分类
单列集合 (集合中一个元素保存一个数据) Collection
双列集合 (集合中一个元素保存两个数据) Map
集合的架构
在这里插入图片描述

Collection接口

单列集合的顶层接口
方法:

  • add方法向集合集合中添加元素
  • clear方法,清空集合中所有元素
  • contains方法 判断集合是否包含某个元素
  • isEmpty判断集合是否为空
  • remove方法 移除集合中元素,返回boolean类型。如果集合中不包含次元素,则删除失败
  • size()返回集合中元素的个数
  • toArray将集合转换成数组。
  • addAll 向一个集合中添加另一个集合
  • containsAll 判断一个集合中是否包含另一个集合
  • removeAll 从一个集合中移除另一个集合
  • retainAll() 只保留在传入集合中有的元素
    返回一个List对象(日常开发经常用到)
    List strings = Arrays.asList(“a”, “b”, “c”);
    System.out.println(strings);
public class Demo08 {
    public static void main(String[] args) {
        Collection coll=new ArrayList();

        //添加
        coll.add("张三");
        coll.add(1);
        coll.add("李四");
        System.out.println(coll);

        //移除
        coll.remove("李四");
        System.out.println(coll);

        //是否包含
        System.out.println(coll.contains("李四"));
        System.out.println(coll.contains("张三"));

        //元素个数
        System.out.println(coll.size());

        //转成数组
        System.out.println(coll.toArray().length);

//        //清除
//        coll.clear();
//        System.out.println(coll);

        //是否为空
        System.out.println(coll.isEmpty());
        System.out.println("-------------------------------");

        //
        Collection coll1=new ArrayList();
        coll1.add("1");
        coll1.add("2");
        coll1.add("3");
        coll1.add("4");
        Collection coll2=new ArrayList();
        coll2.add("3");
        coll2.add("4");
        //添加指定集合的都有元素
        coll1.addAll(coll2);
        System.out.println(coll1);
        //判断是否包含指定集合的所有元素
        System.out.println(coll1.containsAll(coll2));



        //仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。
        System.out.println(coll1.retainAll(coll2));
        System.out.println(coll1);

        //移除指定集合的所有元素
        coll1.removeAll(coll2);
        System.out.println(coll1);

        //返回一个List对象(日常开发经常用到)
        List<String> strings = Arrays.asList("a", "b", "c");
        System.out.println(strings);


    }
}

迭代器

迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。
迭代器原理
迭代器原理

public class Demo09 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("张三");
        list.add("李四");
        list.add("王五");
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            String s = (String) iterator.next();
            if (s.equals("李四")){
                //迭代器移除元素
                iterator.remove();
            }
            System.out.println(s);
        }
        System.out.println("------------------");
        System.out.println(list);
        Iterator<String> iterator1 = list.iterator();
        while (iterator1.hasNext()){
            String s = iterator1.next();
            System.out.println(s);
        }
    }
}

迭代器使用常见问题

  • 1、迭代器迭代完成之后,迭代器的位置在最后一位。 所以迭代器只能迭代一次
  • 2、迭代器在迭代的时候,不要调用多次next方法,可能会出错 NoSuchElementException
  • 3、在迭代器迭代的时候,不能向集合中添加或者删除元素 ConcurrentModificationException

ArrayList类

常用方法:

  • add(int index, E element)
  • remove(int index)
  • set(int index, E element)
  • get(int index)
  • size()
  • subList(int beginIndex,int endIndex) 左闭右开
  • list.listIterator();
package com.qf.demo;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

/*
 *@title Demo02
 *@description
 *@author GaoQk
 *@version 1.0
 *@create 2023/8/2 11:23
 */
public class Demo02 {
    public static void main(String[] args) {
        ArrayList<String> arrList = new ArrayList<>();
        arrList.add("张三");
        arrList.add("李四");
        arrList.add("王五");
        //根据下标添加元素
        arrList.add(1,"赵四");
        System.out.println(arrList);
        System.out.println("---------------");
        //根据下标移除元素
        arrList.remove(1);
        System.out.println(arrList);
        System.out.println("------------------");
        //根据下标获取元素
        System.out.println(arrList.get(1));
        //根据下标修改元素
        arrList.set(1,"赵四");
        System.out.println(arrList);

        //截取集合[),从a下标截取到b下标,不包含b,原来的集合不变,返回新的集合
        List<String> list = arrList.subList(1, 2);
        System.out.println(list);
        System.out.println(arrList);
        System.out.println("-------------------------");

//        //ArrayList中的迭代器
//        ListIterator<String> sli = arrList.listIterator();
//        //往后移动
//        while (sli.hasNext()){
//            String s = sli.next();
//            System.out.println(s);
//        }
//        //可以往前移动
//        while (sli.hasPrevious()){
//            String s = sli.previous();
//            System.out.println(s);
//        }
        System.out.println("---------------------------------");
    }
}

ArrayList遍历的4种方法:

//遍历
        //1.普通for循环遍历
        for (int i = 0; i < arrList.size(); i++) {
            System.out.println(arrList.get(i));
        }
        //2.迭代器遍历
        Iterator<String> iterator = arrList.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        //3.增强for循环,foreach
        for (String s:arrList) {
            System.out.println(s);
        }
        //4.ArrayList 特有的迭代器
        //ArrayList中的迭代器
        ListIterator<String> sli = arrList.listIterator();
        //往后移动
        while (sli.hasNext()){
            String s = sli.next();
            System.out.println(s);
        }
        //可以往前移动
        while (sli.hasPrevious()){
            String s = sli.previous();
            System.out.println(s);
        }

ArrayList实现了特有的迭代器

 //4.ArrayList 特有的迭代器
        //ArrayList中的迭代器
        ListIterator<String> sli = arrList.listIterator();
        //往后移动
        while (sli.hasNext()){
            String s = sli.next();
            System.out.println(s);
        }
        //可以往前移动
        while (sli.hasPrevious()){
            String s = sli.previous();
            System.out.println(s);
        }

ArrayList底层实现原理:
ArrayList其底层实现使用数组 ,添加时才进行扩容,每次扩容到原来的1.5倍 ,查找快,增删慢

说明:第一次添加时,将数组长度扩容到10;不是第一次扩容,就判断如果有效个数size()+1大于数组长度,就需要扩容,每次扩容数组的一半
在这里插入图片描述

LinkedList类

常用的方法与ArrayList一致。自己独有一些向首尾添加移除等方法(可以模拟对列、堆栈等数据结构)

方法代码:

//LinkedList实际工作中很少用到
        LinkedList<String> linkedList = new LinkedList<>();
        //添加
        linkedList.add("张三");
        linkedList.add("李四");
        System.out.println(linkedList);
        //从首部添加
        linkedList.addFirst("王五");
        //从末尾添加
        linkedList.addLast("赵六");
        System.out.println(linkedList);

        //获取
        System.out.println(linkedList.get(0));

        //获取头部
        System.out.println(linkedList.getFirst());
        //获取尾部
        System.out.println(linkedList.getLast());
        System.out.println("---------------------");

模拟队列

//模拟队列,先进先出
        linkedList = new LinkedList<>();
        //向队列的尾部添加元素
        linkedList.offer("张三");
        linkedList.offer("李四");
        linkedList.offer("王五");
//        //对LinkedList,可以移除元素
//        System.out.println(linkedList.poll());
//        System.out.println(linkedList.poll());
//        System.out.println(linkedList.poll());
        //获取但不移除队列的头部元素
        System.out.println(linkedList.peek());
        System.out.println(linkedList.element());
        System.out.println(linkedList);

模拟栈

/模拟栈 先进后出
        linkedList = new LinkedList<>();
        //将元素推入此列表所表示的堆栈
        linkedList.push("张三");
        linkedList.push("李四");
        linkedList.push("王五");

        //从栈的末尾弹出,并移除对象
        System.out.println(linkedList.pop());
        System.out.println(linkedList);

LinkedList实现原理
LinkedList底层使用双向链表实现(增删快、查询慢)
在这里插入图片描述
堆栈和队列结构
在这里插入图片描述

Vector类

ArrayList的方法基本一致
ArrayListLinkedListVector 的区别:

  • ArrayList和Vector底层使用数组实现(增删慢、查询快)
    • ArrayList是当添加元素的时候,才会扩容数组,默认长度为10, Vector是当创建对象的是,就创建长度为10的数组
    • ArrayList线程不安全,效率高 Vector是线程安全的,效率低
  • LinkedList底层使用双向链表实现(增删快、查询慢)

HashSet类

常用方法与Collection接口中定义的方法一致
特点:

  • 无序 (插入顺序)
  • 无下标
  • 不可重复
    方法:
HashSet<String> hashSet = new HashSet<>();
        hashSet.add("zs");
        hashSet.add("ls");
        hashSet.add("ww");
        hashSet.add("zl");
        System.out.println(hashSet);

        //for循环遍历
        for (String s:hashSet){
            System.out.println(s);
        }
        //迭代器遍历,如果删除需要用迭代器删除
        Iterator<String> iterator = hashSet.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
            iterator.remove();

        }

去重原理:先判断hashcode,在判断equals()方法,两者都相等,才是同一个对象,否则不是
判断对象是否相同要重写hashcode()方法和equals()方法

//HashSet去重原理:先判断hashcode,在判断equals()方法,两者都相等,才是同一个对象,否则不是
        HashSet<User> hashSet = new HashSet<>();
        hashSet.add(new User("张三",10));
        hashSet.add(new User("张三",10));
//        hashSet.add(new User("lisi",20));
//        hashSet.add(new User("王五",15));
        System.out.println(hashSet);

LinkedHashSet类

特点::

  • 1、有序
  • 2、无下标
  • 3、不可重复
    与父类的方法一致,去重的原理,也与父类一致

TreeSet类

TreeSet特点:

  • 1、无序(但是有字典顺序)
  • 2、无下标
  • 3、不可重复
    常用方法
    HashSet类的方法一致
    特点:
    使用TreeSet集合存储对象的时候,对象必须要实现Comparable接口
    实现原理
    TreeSet在存储元素的时候,会调用compareTo方法。两个作用:
  • 1、排序: 返回值大于0升序,返回值小于0降序
  • 2、去重(返回值为0) TreeSet认为返回0,两个对象就是相同的对象
  • 3、写成表达式,要根据实现情况判断是升序还是降序(this在前面就是升序,反之降序)
public class Demo01 {
    public static void main(String[] args) {
        //TreeSet 去重,按字典顺序排序(a,b,c)
        TreeSet<String> treeSet = new TreeSet<>();
        treeSet.add("zs");
        treeSet.add("ls");
        treeSet.add("ww");
        treeSet.add("zs");
        System.out.println(treeSet);
        System.out.println("----------------------");
        //增强for循环
        for (String s : treeSet) {
            System.out.println(s);
        }

        Iterator<String> iterator = treeSet.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());

        }

        TreeSet<Person> treeSet1 = new TreeSet<>();
        treeSet1.add(new Person("zs",20));
        treeSet1.add(new Person("ls",80));
        treeSet1.add(new Person("zs",10));
        treeSet1.add(new Person("ww",10));

        System.out.println(treeSet1);

    }
}
//必须实现Comparable接口
class Person implements Comparable<Person>{
    String name;
    Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

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

    //实现compareTo方法
    @Override
    public int compareTo(Person o) {
        if (!this.name.equals(o.name)){
            return this.name.compareTo(o.name);
        }else {
            return this.age-o.age;
        }

    }
}

Collections工具类

常用的方法:
Collections.reverse(List<?> list)

  • 将集合中的元素反转
    Collections.shuffle(List<?> list)
    • 将集合中的元素随机打乱
      Collections.sort(List<?> list)
    • 将集合中的元素排序
    • 自定义排序规则,实现Comparator接口
		 //反转
        List<Integer> list = Arrays.asList(1, 2, 5, 1, 3);
        Collections.reverse(list);
        System.out.println(list);
        //随机打乱
        List<Integer> list1 = Arrays.asList(1, 8, 27, 63, 1);
        Collections.shuffle(list1);
        System.out.println(list1);
        

sort()方法排序

//sort()排序
        List<String> list = Arrays.asList("abc", "aa", "df", "asc");
        Collections.sort(list);
        System.out.println(list);

        List<Integer> list1 = Arrays.asList(1, 9, 4, 8, 7, 2);
        Collections.sort(list1);
        System.out.println(list1);
        List<Student> list2 = Arrays.asList(new Student("zs", 20), new Student("ls", 20), new Student("zs", 21));
        Collections.sort(list2, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                if (!o1.name.equals(o2.name)){
                    return o1.name.compareTo(o2.name);
                }
                return o1.age-o2.age;
            }
        });
        System.out.println(list2);
    }
}
class Student{
    String name;
    Integer age;

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

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

Map集合

Map集合特点
  • Map集合是双列集合,由key和value组成。称之为键值对
  • 键的特点:无序,无下标,不重复。
  • 值的特点:无序,无下标,可重复
    Map集合体系结构
    在这里插入图片描述

HashMap

HashMap基本使用
常用方法

  • put(K key, V value)
  • get(Object key)
  • Set keySet()
  • Collection values()
  • Set<Map.Entry<K,V>> entrySet() 用于遍历
  • boolean containsKey(Object key) 是否包含key
  • boolean containsValue(Object value) 是否包含value
  • V remove(Object key)
  • int size()
HashMap<String, String> map = new HashMap<>();
        //添加
        map.put("cn","中国");
        map.put("rb","日本");
        map.put("jp","小日本");
        map.put("cn","中华人民共和国");
        //获取value
        System.out.println(map.get("cn"));

        //移除
        String s = map.remove("rb");
        System.out.println(s);
        System.out.println(map);

        //判断key和value是否存在
        System.out.println(map.containsKey("cn"));
        System.out.println(map.containsValue("小日本"));

        //是否为空
        System.out.println(map.isEmpty());

        //元素个数
        System.out.println(map.size());

        //遍历
        Set<String> key = map.keySet();
        for (String s1:key){
            System.out.println(map.get(s1));
        }

        Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String,String> entry:entries){
            System.out.println(entry.getKey());
            System.out.println(entry.getValue());
        }

        //清空
        map.clear();
        System.out.println(map);

HashMap的实际应用

public class Demo05 {
    public static void main(String[] args) {
        //用HashMap代替实体类
        Stu stu1 = new Stu("zs", 20);
        System.out.println(stu1);
        HashMap<String, Object> map = new HashMap<>();
        map.put("name","zs");
        map.put("age",20);
        System.out.println(map);


        //集合的嵌套使用
        List<Stu> stus = Arrays.asList(new Stu("ls", 10), new Stu("ww", 10));
        System.out.println(stus);
        HashMap<String, Object> map1 = new HashMap<>();
        HashMap<String, Object> map2 = new HashMap<>();
        map1.put("name","ls");
        map1.put("age",10);
        map2.put("name","ww");
        map2.put("age",10);
        List<HashMap<String, Object>> list = Arrays.asList(map1, map2);
        System.out.println(list);
        //集合嵌套使用
        List<String> list1 = Arrays.asList("济南", "青岛", "烟台");
        List<String> list2 = Arrays.asList("南京", "苏州", "无锡");
        HashMap<String, Object> shandong = new HashMap<>();
        HashMap<String, Object> jiangsu = new HashMap<>();
        shandong.put("山东",list1);
        jiangsu.put("江苏",list2);
        List sd = (List) shandong.get("山东");
        List js = (List) jiangsu.get("江苏");
        System.out.println(sd);
        System.out.println(js);


    }
}
class Stu{
    String name;
    Integer age;


    public Stu(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

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

HashMap的相关实现(重要)
HashMap底层是用Hash表实现,分为数组+链表+红黑树

HashMap 默认初始长度16 , 阈值12 扩容因子 0.75

如果元素个数大于阈值,数组的长度增长一倍,阈值增长一倍

当链表的元素个数大于等于8,数组的长度大于等于64,把链表转化成红黑树

扩容因子0.75?

大于0.75,空间利用率高,查询慢

小于0.75,空间利用率低,查询快

put方法是有返回值,是覆盖,把原来的value返回 ,不是覆盖,返回null

Hashtable

Hashtable常用方法与HashMap一致
HashMap与Hashtable区别:
- 1、Hashtable是线程安全的,HashMap是线程不安全的
- 2、Hashtable中不允许存储null作为key和value,而HashMap可以
在实际开发中一般都是用HashMap。考虑线程安全使用ConCurrentHashMap

泛型的使用

泛型类
泛型类 类名

public class Box<T> {  //T:表示任意的java类型       E、K、V
	private T data;

	public T getData() {
		return data;
	}

	public void setData(T data) {
		this.data = data;
	}
}

泛型接口
泛型接口 接口名

public interface MyInterface<T> {
	public void show(T t);
}

泛型方法
泛型方法 public T 方法名(T t,…){}

//泛型可以作为参数,(必须得先定义  <T> )
public <T> void m1(T t) {
    
}

泛型上下边界
语法:

  • 上边界 ? extends 类型 类型是?的父类
  • 下边界 ? super 类型 类型是?的子类
public class Demo01 {
	//? 表示不确定类型     此时的?表示Object
	public static void test01(List<?> list) {
		
	}
	/**
	 * 定义泛型上边界
	 * 
	 * <? extends 类型>
	 */
	
	public static void test02(List<? extends Number> list) {
		
	}
	/**
	 * 定义泛型下边界
	 * 
	 * <? super 类型>
	 */
	
	public static void test03(List<? super Number> list) {
		
	}
	
	public static <T> void test04(List<? extends Comparable<T>> list) {
		
	}
	public static void main(String[] args) {
		List<String> list1 = new ArrayList<String>();
		List<Integer> list2 = new ArrayList<Integer>();
		List<Number> list3 = new ArrayList<Number>();
		List<Object> list4 = new ArrayList<Object>();
		test01(list1);
		test01(list2);
		test01(list3);
		test01(list4);
		
		//test02(list1);  //错误,方法定义泛型的上边界,泛型只能是Number及其Number子类
		test02(list2);
		test02(list3);
		//test02(list4);  //错误,方法定义泛型的上边界,泛型只能是Number及其Number子类 
		
		//test03(list1);  //错误,方法定义泛型的下边界,泛型只能是Number及其Number父类
		//test03(list2);
		test03(list3);
		test03(list4);
        
		test04(list1);
		test04(list2);
		//test04(list3);    //错误,方法定义泛型的上边界,泛型必须实现Comparable接口
		//test04(list4);      //错误,方法定义泛型的上边界,泛型必须实现Comparable接口
	}	
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值