快速掌握Java中List和Set接口的基本使用

简介: 快速掌握Java中List和Set接口的基本使用

集合的概念


是一个工具类,作用为存储多个数据,通常用于替代数组


集合的特点


只能存放Object对象

只能存放引用类型

不能存放接口,只能存放接口实现类对象

来自java.util包

List接口


List的存储特点


有序、有下标、元素可以重复

常用实现类

ArrayList 最常用

JDK1.2 底层数组实现 查询快、增删慢 线程不安全,效率高

一般不用

JDK1.2 底层链表实现 增删快,查询慢 线程不安全,效率高

Vector 不用

JDK1.0 底层数组实现 都慢 线程安全,效率低

创建


通常使用多态


List 集合名=new 实现类名();


常用方法


集合名.方法名


boolean add(元素):将元素添加至集合末尾

void add(下标,元素):将元素添加至指定下标位置

boolean addAll(集合名):将指定集合所有元素添加至当前集合末尾

boolean addAll(下标,集合名):将指定集合所有元素添加至当前集合指定下标位置

void clear():清空集合元素

int size():获取集合长度

boolean contains(元素):判断集合中是否包含指定元素

boolean containsAll(集合名):判断集合中是否包含指定集合的所有元素

元素 get(下标):获取指定下标位置上的元素

int indexOf(元素):获取指定元素第一次出现的下标,不存在返回-1

int lastIndexOf(元素):获取指定元素最后一次出现的下标,不存在返回-1

boolean isEmpty():判断集合元素是否为空,不能判比null值

元素 remove(下标):移除指定下标的元素,返回该元素

元素 set(下标,新值):将指定下标位置的值替换为新值,返回旧值

void sort(比较器实现类对象):对集合元素按照指定规则排序

Object[] toArray():将集合转换为数组


代码示例


public class Test {
        public static void main(String[] args) {
            List list = new ArrayList();
            list.add(66);
            list.add(5);
            list.add(77);//66 5 77
            list.add(2,44);//66 5 44 77
            List list2 = new ArrayList();
            list2.add(2);
            list2.add(1);
            list.addAll(list2);//66 5 44 77 2 1
            list.addAll(1, list2);//66 2 1 5 44 77 2 1
            System.out.println("清空之前:"+list.size());
           // list.clear();
           // System.out.println("清空之后:"+list.size());
            System.out.println(list.contains(5));//t
            System.out.println(list.containsAll(list2));//t
            List list3 = new ArrayList();
            list3.add(66);
            list3.add(77);
            list3.add(88);
            System.out.println(list.containsAll(list3));//f
            System.out.println(list.get(3));//5
            System.out.println(list.indexOf(88));//-1
            System.out.println(list.lastIndexOf(2));//6
            //list.clear();
            System.out.println(list.isEmpty());
            List list4=null;
            //System.out.println(list4.isEmpty()); 空指针异常
            System.out.println(list.remove(3));//66 2 1 44 77 2 1
            // System.out.println(list.remove(2));
            list.set(1, 88);//66 88 1 44 77 2 1
            Object[] os=list.toArray();
            for(int i=0;i<os.length;i++){
                System.out.print(os[i]+" ");
            }
            System.out.println();
        }
    }


遍历方法


for+get()
 for (int i = 0; i < 集合名.size(); i++) {
       //i代表当前下标
       //通过集合名.get(i)的方式获取当前元素
   }
   如:
 for (int i = 0; i < list.size(); i++) {
        System.out.print(list.get(i)+" ");
         }
        System.out.println();


迭代器遍历

hasNext():判断是否存在下一元素
next():指针后移,获取下一元素
//获取迭代器对象
Iterator it=集合名.iterator();
while(it.hasNext()){//集合存在下一元素则继续后续操作
//通过it.next()使指针后移,得到元素
}
如:
Iterator it=list.iterator();
while(it.hasNext()){
System.out.print(it.next()+" ");
}
System.out.println();
tips:迭代过程中不允许对集合进行增删操作
外遍历forEach
for(数据类型 元素名(随便起) : 集合名){
//元素名就代表当前元素
}
如:
for (Object o: list) {
System.out.print(o+" ");
}
System.out.println();
本质也是迭代器遍历,内部不允许进行增删操作
JDK5.0
自遍历forEach
//匿名内部类
集合名.forEach(new Consumer() {
@Override
public void accept(Object o) {
//o就代表当前元素
}
});
 //lambda简化
         集合名.forEach(o-> {o就代表当前元素});
 如:
         list.forEach(new Consumer() {
             @Override
             public void accept(Object o) {
                 System.out.print(o + " ");
             }
         });
         System.out.println();
         // lambda
         list.forEach(o-> System.out.print(o+" "));


JDK8.0

泛型

作用


用于集合中,可以约束集合存储的数据类型


语法


List<数据类型> 集合名=new 实现类名<数据类型>();

1

使用


1. 如果集合中存放基本类型,则泛型必须声明为其包装类型

2. 声明泛型之后,集合中不允许存放其他类型的数据

3. 前后类型声明必须一致

4. 等号后边的泛型不声明,语法不规范

5. 等号前边的泛型不声明,泛型无意义


List<Integer> list = new ArrayList<Integer>();
        list.add(66);
        list.add(88);
       /* list.add("abc");
        list.add(5.5);*/
        list.forEach(new Consumer<Integer>() {
            @Override
            public void accept(Integer i) {
                System.out.println(i);
            }
        });


Set接口

Collection


是一个接口

是List和Set的父接口

所有集合都由Collection或Map派生

特点


存放着List和Set的共有方法

没有自己的直接实现类

Set的存储特点

无序、无下标、元素不可重复

常用实现类

HashSet

JDK1.2 底层哈希表实现(数组+链表 又名散列表) 线程不安全,效率高

LinkedHashSet

JDK1.2 是HashSet的子类,底层哈希表实现 线程不安全,效率高

TreeSet

JDK1.2 是SortedSet的实现类,底层红黑树实现 线程不安全,效率高

创建


利用多态


Set<泛型类型> 集合名 = new 实现类名<泛型类型>();


常用方法


全部继承自Collection

遍历方法

Iterator迭代器遍历

外遍历forEach

自遍历forEach

哈希表的去重过程


先通过调用元素的hashCode()方法得到哈希码值

然后通过哈希码值%数组长度得到存放下标

若该下标位置未存放元素,则直接存放

若已存有元素,则调用当前元素的equals()方法与其位置的所有元素进行值的比较

都不相同,则链表存放

若有相同,舍弃当前元素


注意事项

当集合中存放的为自定义类型时,必须重写hashCode和equals才能保证去重

LinkedHashSet能够保证元素存入和取出顺序一致

TreeSet可以实现对元素进行默认的升序排序

如果存放的为自定义类型,必须重写排序规则

两种排序方式:

实现Comparable接口,重写compareTo方法

要对谁排,就让谁实现

原理:让当前对象与参数对象进行比较

返回值规则:

从小到大:this的值>o的值,返回正数

从大到小:this的值>o的值,返回负数

相等返回0

实现Comparator接口,重写compare方法

在集合创建处的小括号内传入该接口的实现类对象


 

public class Test2 {
            public static void main(String[] args) {
                Set<Student> set = new TreeSet<Student>(new Comparator<Student>() {
                    @Override
                    public int compare(Student o1, Student o2) {
                        //根据学生年龄从大到小排序
                        return o2.getAge()-o1.getAge();
                    }
                });
                set.add(new Student("张三", 20));
                set.add(new Student("lisi", 21));
                set.add(new Student("lisi", 21));
                set.add(new Student("wangwu", 22));
                set.add(new Student("maliu", 19));
                set.forEach(s-> System.out.println(s));
            }
        }


默认识别第一种排序方式

第二种排序方式优先级高于第一种

List和set的区别

基本概念的区别

List 接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素。List 接口存储一组不唯一,有序的对象。


Set 具有与 Collection 完全一样的接口,只是行为上不同,Set 不保存重复的元素。Set 接口存储一组唯一,无序的对象。


1.Set 接口实例存储的是无序的, 不重复的数据, List 接口实例存储的是有序的,可以重复的元素;

2.Set检索效率低下, 删除和插入效率高, 插入和删除不会引起元素位置改变

3.List和数组类似, 可以动态增长, 根据实际存储的数据的长度自动增长List的长度, 查找元素效率高, 插入删除效率低, 因为会引起其他元素位置改变 <实现类有ArrayList,LinkedList,Vector> ;

使用场景

List


常用的实现类有 ArrayList、LinkedList 和 Vector。ArrayList 最为流行,它提供了使用索引的随意访问,而 LinkedList 则对于经常需要从 List 中添加或删除元素的场合更为合适。

set


Set 接口最流行的几个实现类是 HashSet、LinkedHashSet 以及 TreeSet。最流行的是基于 HashMap 实现的 HashSet;TreeSet 还实现了 SortedSet 接口,因此 TreeSet 是一个根据其 compare() 和 compareTo() 的定义进行排序的有序容器。

相关文章
|
5天前
|
存储 Java 编译器
Java中的抽象类与接口,在阿里工作5年了
Java中的抽象类与接口,在阿里工作5年了
|
6天前
|
Java 开发者
Java一分钟之-Lambda表达式与函数式接口
【5月更文挑战第12天】Java 8引入的Lambda表达式简化了函数式编程,与函数式接口结合,实现了代码高效编写。本文介绍了Lambda的基本语法,如参数列表、箭头符号和函数体,并展示了如何使用Lambda实现`Runnable`接口。函数式接口仅有一个抽象方法,可与Lambda搭配使用。`@FunctionalInterface`注解用于确保接口具有单一抽象方法。文章还讨论了常见的问题和易错点,如非函数式接口、类型冲突以及Lambda表达式的局部变量可见性,并提供了避免这些问题的策略。通过理解Lambda和函数式接口,开发者能提高代码可读性和效率。
44 4
|
1天前
|
安全 Java 编译器
Java一分钟之——泛型方法与泛型接口
【5月更文挑战第20天】Java泛型提供编译时类型安全检查,提升代码重用和灵活性。本文探讨泛型方法和接口的核心概念、常见问题和避免策略。泛型方法允许处理多种数据类型,而泛型接口需在实现时指定具体类型。注意类型擦除、误用原始类型和泛型边界的理解。通过明确指定类型参数、利用通配符和理解类型擦除来避免问题。泛型接口要精确指定类型参数,适度约束,利用默认方法。示例代码展示了泛型方法和接口的使用。
26 1
Java一分钟之——泛型方法与泛型接口
|
2天前
|
并行计算 Java API
Java 8中的接口默认方法和静态方法以及并行数组
【5月更文挑战第19天】Java 8引入了许多新特性,其中包括接口的默认方法和静态方法,以及并行数组的能力。这些特性增强了Java的面向对象编程模型和数组处理能力。让我们深入了解它们的概念和实践。
20 2
|
3天前
|
存储 Java
Java一分钟之-高级集合框架:Queue与Deque接口
【5月更文挑战第18天】本文探讨Java集合框架中的`Queue`和`Deque`接口,两者都是元素序列的数据结构。`Queue`遵循FIFO原则,主要操作有`add/remove/element/peek`,空队列操作会抛出`NoSuchElementException`。`Deque`扩展`Queue`,支持首尾插入删除,同样需注意空`Deque`操作。理解并正确使用这两个接口,结合具体需求选择合适数据结构,能提升代码效率和可维护性。
29 4
|
6天前
|
Java API 容器
Java8函数式编程接口:Consumer、Supplier、Function、Predicate
Java8函数式编程接口:Consumer、Supplier、Function、Predicate
8 1
|
6天前
|
Java ice
【Java开发指南 | 第二十九篇】Java接口
【Java开发指南 | 第二十九篇】Java接口
10 0
|
6天前
|
Java
【Java开发指南 | 第九篇】访问实例变量和方法、继承、接口
【Java开发指南 | 第九篇】访问实例变量和方法、继承、接口
15 4
|
6天前
|
安全 Java 调度
Java一分钟:多线程编程初步:Thread类与Runnable接口
【5月更文挑战第11天】本文介绍了Java中创建线程的两种方式:继承Thread类和实现Runnable接口,并讨论了多线程编程中的常见问题,如资源浪费、线程安全、死锁和优先级问题,提出了解决策略。示例展示了线程通信的生产者-消费者模型,强调理解和掌握线程操作对编写高效并发程序的重要性。
47 3
|
6天前
|
Java API
Java 接口
5月更文挑战第6天