JavaSE学习笔记(四)集合_Collection_List

本文详细探讨了数组与集合在Java中的特点,集合的动态扩容、增删操作优势,以及Collection、List、Set系列接口的深入解析,包括常用API和遍历方式。同时涵盖了ArrayList、LinkedList和Collections工具类的实例演示,以及泛型在集合中的应用。
摘要由CSDN通过智能技术生成

1 为什么用集合?

  • 数组的特点
    • 数组定义完成并启动后,类型确定、长度固定
    • 不适合元素的个数和类型不确定的业务场景,更不适合做需要增删数据操作
    • 数组的功能比较的单一,处理数据的能力并不是很强大
  • 集合的特点
    • 集合的大小不固定,启动后可以动态变化,类型也可以选择不固定
    • 集合非常适合元素个数不能确定,且需要做元素的增删操作的场景
    • 集合提供的种类特别的丰富,功能非常强大,开发中集合用的更多

2 集合类体系结构

集合类体系结构

  • Collection单列集合,每个元素(数据)只包含一个值
  • Map双列集合,每个元素包含两个值(键值对)

3 Collection集合

  • List系列集合:添加的元素是有序、可重复、有索引
    • ArrayListLinekdList :有序、可重复、有索引
  • Set系列集合:添加的元素是无序、不重复、无索引
    • HashSet:无序、不重复、无索引
    • LinkedHashSet:有序、不重复、无索引
    • TreeSet:按照大小默认升序排序、不重复、无索引

3.1 Collection常用API

  • Collection是单列集合的祖宗接口,它的功能是全部单列集合都可以继承使用的
方法名称说明
public boolean add(E e)把给定的对象添加到当前集合中
public void clear()清空集合中所有的元素
public boolean remove(E e)把给定的对象在当前集合中删除
public boolean contains(Object obj)判断当前集合中是否包含给定的对象
public boolean isEmpty()判断当前集合是否为空
public int size()返回集合中元素的个数
public Object[] toArray()把集合中的元素,存储到数组中

代码示例

public class CollectionDemo {
    public static void main(String[] args) {
        Collection<String> c = new ArrayList<>();
        // 1.添加元素, 添加成功返回true。
        c.add("Java");
        c.add("HTML");
        System.out.println(c.add("HTML")); // true
        c.add("MySQL");
        c.add("Java");
        System.out.println(c); // [Java, HTML, HTML, MySQL, Java]

        // 2.清空集合的元素。
        c.clear();
        System.out.println(c);

        // 3.判断集合是否为空 是空返回true,反之。
        System.out.println(c.isEmpty());

        // 4.获取集合的大小。
        System.out.println(c.size());

        // 5.判断集合中是否包含某个元素。
        System.out.println(c.contains("Java"));  // true
        System.out.println(c.contains("java")); // false

        // 6.删除某个元素:如果有多个重复元素默认删除前面的第一个!
        System.out.println(c.remove("java")); // false
        System.out.println(c);
        System.out.println(c.remove("Java")); // true
        System.out.println(c);

        // 7.把集合转换成数组  [HTML, HTML, MySQL, Java, 黑马]
        Object[] arrs = c.toArray();
        System.out.println("数组:" + Arrays.toString(arrs));

        System.out.println("----------------------拓展----------------------");
        Collection<String> c1 = new ArrayList<>();
        c1.add("java1");
        c1.add("java2");
        Collection<String> c2 = new ArrayList<>();
        c2.add("赵敏");
        c2.add("殷素素");
        // addAll把c2集合的元素全部倒入到c1中去。
        c1.addAll(c2);
        System.out.println(c1); // [java1, java2, 赵敏, 殷素素]
        System.out.println(c2); // [赵敏, 殷素素]
    }
}

3.2 Collection三种遍历方式

  • 遍历就是一个一个的把容器中的元素访问一遍

3.2.1 迭代器

  • 迭代器在Java中的代表是Iterator,迭代器是集合的专用的遍历方式
  • 默认指向当前集合的索引’0‘位置
/*
-- 方法:
   public Iterator iterator(): 获取集合对应的迭代器,用来遍历集合中的元素的
   boolean hasNext():判断是否有下一个元素,有返回true ,反之。
   E next():获取下一个元素值!
--流程:
   1.先获取当前集合的迭代器
       Iterator<String> it = lists.iterator();
   2.定义一个while循环,问一次取一次。
       通过it.hasNext()询问是否有下一个元素,有就通过
       it.next()取出下一个元素。
*/
ArrayList<String> lists = new ArrayList<>();
lists.add("方");
lists.add("佬");
lists.add("肆");
System.out.println(lists); // [方,佬,肆]

// 1、得到当前集合的迭代器对象。
Iterator<String> it = lists.iterator();

// 2、定义while循环
while (it.hasNext()){
   System.out.println(it.next());
}

3.2.2 增强for循环

  • 可以遍历集合也可以遍历数组
/*
for(元素数据类型 变量名 : 数组或者Collection集合) {
}  //在此处使用变量即可,该变量就是元素
*/
Collection<String> list = new ArrayList<>();
...
for(String ele : list) {
    System.out.println(ele);
} // 修改第三方变量(ele)的值不会影响到集合中的元素

3.2.3 Lambda表达式

Collection<String> lists = new ArrayList<>();
...
// 三种lambda表达式
lists.forEach(new Consumer<String>() {
   @Override
   public void accept(String s) {
        ystem.out.println(s);
   }
});
list.forEach(s -> {System.out.println(s);});
// 只适用于只有一条java语句的
list.forEach(s ->   System.out.println(s) );

4 List集合

  • ArrayList、LinekdList :有序,可重复,有索引
    • 有序:存储和取出的元素顺序一致
    • 有索引:可以通过索引操作元素
    • 可重复:存储的元素可以重复

4.1 ArrayList

  • ArrayList底层是基于数组实现的,根据查询元素快,增删相对慢
    • 第一次创建集合并添加第一个元素的时候,在底层创建一个默认长度为10的数组
方法名称说明
void add(int index,E element)在此集合中的指定位置插入指定的元素
public int size()返回集合中的元素的个数
E remove(int index)删除指定索引处的元素,返回被删除的元素
public boolean remove(Object o)删除指定的元素,返回删除是否成功
E set(int index,E element)修改指定索引处的元素,返回被修改的元素
E get(int index)返回指定索引处的元素
ArrayList<String> list = new ArrayList<>(); // 一行经典代码!
...
// 1.在某个索引位置插入元素。
list.add(2, "hello");

// 2.返回集合中元素个数
System.out.println(list.size());

// 3.根据索引删除元素,返回被删除元素
System.out.println(list.remove(1));

// 4.根据索引获取元素:public E get(int index):返回集合中指定位置的元素。
System.out.println(list.get(1));

// 5.修改索引位置处的元素: public E set(int index, E element)
System.out.println(list.set(1, "方佬肆"));

4.2 LinkedList

  • LinkedList底层基于双链表实现的,查询元素慢,增删首尾元素是非常快的
方法名称说明
public void addFirst​(E e)在该列表开头插入指定的元素
public void addLast​(E e)将指定的元素追加到此列表的末尾
public E getFirst​()返回此列表中的第一个元素
public E getLast​()返回此列表中的最后一个元素
public E removeFirst​()从此列表中删除并返回第一个元素
public E removeLast​()从此列表中删除并返回最后一个元素
public void push(E e)将元素推入此列表所表示的堆栈
public E pop()从此列表所表示的堆栈处弹出一个元素
// LinkedList可以完成队列结构,和栈结构 (双链表)
// 1、做一个队列:
LinkedList<String> queue = new LinkedList<>();
// 入队
queue.addLast("1");
queue.addLast("2");
queue.addLast("3");
System.out.println(queue); // [1,2,3]
// 出队
// System.out.println(queue.getFirst());
System.out.println(queue.removeFirst()); // 1
System.out.println(queue.removeFirst()); // 2
System.out.println(queue); // [3]

// 2、做一个栈
LinkedList<String> stack = new LinkedList<>();
// 入栈 压栈 (push)
stack.push("1");
stack.push("2");
stack.push("3");
stack.push("4");
System.out.println(stack); // [4,3,2,1]

// 出栈  弹栈 pop
System.out.println(stack.pop()); // 4
System.out.println(stack.pop()); // 3
System.out.println(stack.pop()); // 2
System.out.println(stack); // [1]

5 Collections集合工具类(注意:不是Collection)

  • java.utils.Collections:是集合工具类
  • 作用:Collections并不属于集合,是用来操作集合的工具类

Collections常用API

方法名称说明
public static boolean addAll(Collection<? super T> c, T… elements)给集合对象批量添加元素
public static void shuffle(List<?> list)打乱List集合元素的顺序
List<String> names = new ArrayList<>();
//names.add("楚留香");
//names.add("胡铁花");
//names.add("张无忌");
//names.add("陆小凤");
Collections.addAll(names, "中国","美国", "英国","德国");
System.out.println(names);

// 2、public static void shuffle(List<?> list) :打乱集合顺序。
Collections.shuffle(names);
System.out.println(names);

Collections排序相关API

  • 使用范围:只能对于List集合的排序
方法名称说明
public static void sort(List list)将集合中元素按照默认规则排序
public static void sort(List list,Comparator<? super T> c)将集合中元素按照指定规则排序

注意:第一种方式不可以直接对自定义类型的List集合排序,除非自定义类型实现了比较规则Comparable接口
第一种方式排序(只能对基本数据类型)

List<Integer> list = new ArrayList<>();
Collections.addAll(list, 12, 23, 2, 4);
System.out.println(list); // [12, 23, 2, 4]
Collections.sort(list);
System.out.println(list); // [2, 4, 12, 23]

在类定义时实现Comparable接口

public class Apple implements Comparable<Apple>{
    private String name;
    private String color;
    private double price;
    private int weight;
...
    /**
      方式一:类自定义比较规则
      o1.compareTo(o2)
     * @param o
     * @return
     */
    @Override
    public int compareTo(Apple o) {
        // 按照重量进行比较的
        return this.weight - o.weight ; // 升序排序;List集存储相同大小的元素 会保留!
    }
}

第二种方式排序

public static void main(String[] args) {
        List<Apple> apples = new ArrayList<>(); // 可以重复!
        apples.add(new Apple("红富士", "红色", 9.9, 500));
        apples.add(new Apple("青苹果", "绿色", 15.9, 300));
        apples.add(new Apple("绿苹果", "青色", 29.9, 400));
        apples.add(new Apple("黄苹果", "黄色", 9.8, 500));

//      Collections.sort(apples); // 方法一:可以的,Apple类已经重写了比较规则
//      System.out.println(apples);

//      方式二:sort方法自带比较器对象
        Collections.sort(apples, new Comparator<Apple>() {
            @Override
            public int compare(Apple o1, Apple o2) {
                return Double.compare(o1.getPrice() , o2.getPrice()); // 按照价格排序!!
            } // double类型数据比较时用Double.compare(),防止精度损失
        });
      //Lambda表达式
      //Collections.sort(apples, ( o1,  o2) ->  Double.compare(o1.getPrice() , o2.getPrice()) );
        System.out.println(apples);

    }

6 泛型

泛型概述

  • 泛型:是JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检查
  • 泛型的格式:<数据类型>
  • 注意:泛型只能支持引用数据类型
  • 集合体系的全部接口和实现类都是支持泛型的使用的

泛型的好处

  • 统一数据类型
  • 把运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常,因为编译阶段类型就能确定下来

泛型三种定义

  • 自定义泛型
  • 自定义泛型方法
  • 自定义泛型接口

6.1 自定义泛型类

  • 定义类时同时定义了泛型的类就是泛型类
  • 泛型类的格式:修饰符 class 类名<泛型变量>{}
public class MyArrayList<T>{}
  • 此处泛型变量T可以随便写为任意标识,常见的如E、T、K、V等
  • 作用:编译阶段可以指定数据类型,类似于集合的作用
public class MyArrayList<E> {
    private ArrayList lists = new ArrayList();

    public void add(E e){
        lists.add(e);
    }

    public void remove(E e){
        lists.remove(e);
    }

    @Override
    public String toString() {
        return lists.toString();
    }
}

6.2 自定义泛型方法

  • 定义方法时同时定义了泛型的方法就是泛型方法
  • 泛型方法的格式:修饰符 <泛型变量> 方法返回值 方法名称(形参列表){}
public <T> void show(T t){}
  • 作用:方法中可以使用泛型接收一切实际类型的参数,方法更具备通用性
public static<T> String getString(T[] arr){
	StringBuilder sb = new StringBuilder("[");
	for(int i = 0; i < arr.length; i++){
		sb.append(arr[i]).append( i == arr.length - 1 ? "" : ", " );
	}
	sb.append("]");
	return sb.toString();
}

Integer[] ages = {10, 20, 30};
String s = getString(ages);
System.out.println(s);

6.3 自定义泛型接口

  • 使用了泛型定义的接口就是泛型接口
  • 泛型接口的格式:修饰符 interface 接口名称<泛型变量>{}
public interface Data<E>{}
  • 作用:泛型接口可以让实现类选择当前功能需要操作的数据类型
public interface Data<E> {
    void add(E e);
    void delete(int id);
    void update(E e);
    E queryById(int id);
}
// 实现类必须实现接口内的方法(可用 alt + insert 快速插入重写方法)
public class StudentData implements Data<Student>{
    @Override
    public void add(Student student) {
    }

    @Override
    public void delete(int id) {
    }

    @Override
    public void update(Student student) {
    }

    @Override
    public Student queryById(int id) {
        return null;
    }
}

6.4 泛型通配符

泛型的上下限

  • ? extends Car: ?必须是Car或者其子类 泛型上限
  • ? super Car : ?必须是Car或者其父类 泛型下限
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值