Java中常用的集合及方法(3)

1、List(接上级--常用方法示例补充)

1.4 常用的方法

1.4.2 LinkedList(JDK8)

LinkedList是Java中一个实现了List接口和Deque接口的类,它采用链表结构存储数据,支持高效的插入和删除操作。

LinkedList中的所有方法及使用
使用示例:
1、构造方法
java 复制代码
LinkedList<String> list = new LinkedList<>();
2、添加元素
java 复制代码
// 在链表末尾添加元素
list.add("Apple");

// 在指定索引位置插入元素
list.add(0, "Banana");
3、删除元素
java 复制代码
// 删除第一个元素(头节点)
String removedHead = list.removeFirst();

// 删除最后一个元素(尾节点)
String removedTail = list.removeLast();

// 删除特定对象首次出现的位置
if (list.contains("Apple")) {
    list.removeFirstOccurrence("Apple");
}

// 删除特定对象最后一次出现的位置
if (list.contains("Apple")) {
    list.removeLastOccurrence("Apple");
}

// 移除链表中的第一个元素  
list.remove(); 

// 根据索引删除元素
list.remove(0);

// 移除指定元素(首次出现的)  
list.remove("Apple"); // 如果存在的话,移除Apple


// 移除所有指定元素集合  
list.removeAll(java.util.Arrays.asList("Apple", "Banana")); // 移除所有Apple和Banana(如果存在)
4、获取元素
java 复制代码
// 获取第一个元素(头节点)
String firstItem = list.getFirst();

// 获取最后一个元素(尾节点)
String lastItem = list.getLast();

// 获取索引位置的元素
String itemAtIndex = list.get(0);
5、设置元素
java 复制代码
// 设置第一个元素(头节点)
list.setFirst("Cherry");

// 设置最后一个元素(尾节点)
list.setLast("Cherry");

// 根据索引设置元素
list.set(0, "Cherry");
6、遍历和查找元素
java 复制代码
// 使用迭代器遍历
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

// 使用for-each循环遍历
for (String element : list) {
    System.out.println(element);
}

// 查找元素是否存在
boolean contains = list.contains("Cherry");

// 获取元素的索引
int index = list.indexOf("Cherry");

// 查找指定元素最后一次出现的索引  
int lastIndex = list.lastIndexOf("Banana"); // 查找Banana的最后一个索引(如果只有一个,则和indexOf一样)
7、其他操作
java 复制代码
// 获取列表大小(元素数量)
int size = list.size();

// 清空列表
list.clear();

// 判断列表是否为空
boolean isEmpty = list.isEmpty();

// 在链表头部添加元素
list.addFirst("Orange");

// 在链表尾部添加元素
list.addLast("Grape");

// 从链表头部弹出并返回元素
String poppedHead = list.pop();

// 从链表尾部移除并返回元素
String polledTail = list.pollLast();

// 检查链表是否包含另一个集合的所有元素
boolean allElementsPresent = list.containsAll(anotherList);

// 移除链表中所有与另一个集合相同的元素
list.removeAll(anotherList);

// 截取子列表
List<String> sublist = list.subList(fromIndex, toIndex);
8、排序操作

由于LinkedList实现了List 接口,因此可以使用**Collections.sort()**进行排序,但请注意这将创建一个新的ArrayList来完成排序,并在排序后替换原链表内容。

java 复制代码
Collections.sort(list);

如果是对某个实体类,需要根据不同的字段或逻辑来排序,也可以创建一个Comparator

例:

java 复制代码
import java.util.Collections;  
import java.util.Comparator;  
import java.util.LinkedList;  
  
public class LinkedListExample {  
    public static void main(String[] args) {  
        LinkedList<Person> list = new LinkedList<>();  
        list.add(new Person("Alice", 25));  
        list.add(new Person("Bob", 20));  
        list.add(new Person("Charlie", 30));  
  
        // 自定义排序,按照年龄升序排序  
        Collections.sort(list, new Comparator<Person>() {  
            @Override  
            public int compare(Person p1, Person p2) {  
                return Integer.compare(p1.age, p2.age);  
            }  
        });  
        // 输出: [Bob, Alice, Charlie] 此处Person类需重写toString方法  
        System.out.println(list); 
    }  
}  
  
class Person {  
    String name;  
    int age;  
  
    public Person(String name, int age) {  
        this.name = name;  
        this.age = age;  
    }  
  
    @Override  
    public String toString() {  
        return name + " " + age;  
    }  
}

或者是使用 Java 8 的 Lambda 表达式进行排序:

java 复制代码
import java.util.Collections;  
import java.util.LinkedList;  
import java.util.Comparator;  
  
public class LinkedListExample {  
    public static void main(String[] args) {  
        LinkedList<Person> list = new LinkedList<>();  
        list.add(new Person("Alice", 25));  
        list.add(new Person("Bob", 20));  
        list.add(new Person("Charlie", 30));  
  
        // 使用 Lambda 表达式进行自定义排序,按照年龄升序排序 :Person类需有getAge方法  
        Collections.sort(list, Comparator.comparingInt(Person::getAge));  
  
        // 输出: [Bob, Alice, Charlie] 
        System.out.println(list); 
    }  
}  
  
class Person {  
    String name;  
    int age;  
  
    public Person(String name, int age) {  
        this.name = name;  
        this.age = age;  
    }  
  
    public int getAge() {  
        return age;  
    }  
  
    @Override  
    public String toString() {  
        return name + " " + age;  
    }  
}
适合使用的场景:
  1. 频繁增删的场景:LinkedList在插入和删除元素时具有较高的效率,特别适用于需要频繁进行这些操作的情况。例如,当需要在列表的头部或中间位置插入或删除元素时,LinkedList是一个很好的选择。
  2. 头尾操作或插入指定位置的场景:LinkedList允许在链表的两端以及任何指定位置进行高效的插入和删除操作。这使得它在需要灵活操作列表不同位置的场景中特别有用。
  3. 顺序访问的场景:如果应用需要按照顺序访问列表中的元素,而不是随机访问,那么LinkedList可能是一个合适的选择。因为LinkedList是通过节点链接实现的,所以在顺序访问时性能较好。

注意:

虽然LinkedList在插入和删除操作上具有优势,但在随机访问方面可能不如ArrayList高效。因此,在选择使用LinkedList还是其他数据结构时,需要根据具体应用场景的性能需求进行权衡。

此外,还需要注意LinkedList的内存使用情况。由于LinkedList的每个节点都需要消耗一定的空间来存储数据和指针,因此在处理大量数据时,可能会占用更多的内存。因此,在使用LinkedList时,也需要关注内存管理和优化。

使用场景示例:
  1. 实现队列或栈:LinkedList可以作为队列(Queue)或栈(Stack)的数据结构实现。队列是一种先进先出(FIFO)的数据结构,常用于处理需要按顺序处理的任务或事件,如打印任务队列。栈是一种后进先出(LIFO)的数据结构,常用于需要按相反顺序处理元素的情况,如函数调用栈。LinkedList的节点可以通过其指针关系方便地实现这些操作。
  2. 链表操作算法:在需要实现链表相关的算法时,LinkedList是一个很好的选择。例如,你可以使用LinkedList来实现链表的合并、反转、排序等算法。这些算法通常需要对链表进行频繁的插入和删除操作,LinkedList的高效性使得这些算法的实现更加高效。
  3. 动态插入和删除元素:在某些应用中,可能需要频繁地在列表的任意位置插入或删除元素。例如,在一个需要用户动态添加和删除任务的待办事项列表中,LinkedList就能够提供高效的插入和删除操作。由于LinkedList不需要像ArrayList那样移动大量元素来保持连续的内存空间,因此在这种场景下,LinkedList的性能优势会更为明显。
使用时需要注意的问题:

在使用LinkedList时,需要注意以下几个关键问题:

  1. 节点数据的准确性:确保链表中的每个节点都包含正确的数据。在插入或修改节点数据时,需要仔细核对数据的正确性,避免因为数据错误导致链表的状态不一致。

  2. 节点指针的正确性:LinkedList中的每个节点都有一个指向下一个节点的指针。在插入、删除或修改节点时,必须确保这些指针的正确性。如果指针设置错误,可能会导致链表断裂或形成循环,从而破坏链表的完整性。

  3. 内存管理:在创建新节点时,需要分配内存;在删除节点时,需要释放内存。必须确保在合适的时机进行内存分配和释放,避免内存泄漏或内存不足的问题。

  4. 并发安全:LinkedList不是线程安全的。在多线程环境下,如果多个线程同时修改LinkedList,可能会导致数据不一致或其他并发问题。因此,在并发环境下使用LinkedList时,需要采取适当的同步措施,例如使用锁或同步块来保护链表的访问和修改操作。

  5. 遍历和访问方式:LinkedList是基于节点链接实现的,因此在遍历和访问链表元素时,需要使用迭代器或循环遍历的方式。在遍历过程中,需要注意避免死循环或跳过某些节点的问题。同时,由于LinkedList在随机访问方面不如ArrayList高效,因此在需要频繁进行随机访问的场景下,ArrayList可能更合适。

  6. 性能考虑:虽然LinkedList在插入和删除元素时具有较高的效率,但在遍历元素时可能不如ArrayList快。因此,在选择使用LinkedList还是ArrayList时,需要根据具体应用场景的性能需求进行权衡。

LinkedList的扩容?

注意:LinkedList不存在扩容的说法

因为LinkedList是基于双向链表实现的,它没有固定的初始化大小,也没有特定的扩容机制。原因在于链表结构的特点使其可以在需要时动态地添加或删除节点,而不需要像数组那样预先分配或调整固定大小的内存空间。因此,LinkedList在添加元素时,只需要在链表头部或尾部创建新的节点,或者在指定位置插入新的节点即可。

相关推荐
练习时长两年半的Java练习生(升级中)10 分钟前
从0开始学习Java+AI知识点总结-18.web基础知识(Java操作数据库)
java·学习·web
计算机程序员小杨34 分钟前
计算机专业的你懂的:大数据毕设就选贵州茅台股票分析系统准没错|计算机毕业设计|数据可视化|数据分析
java·大数据
y1y1z38 分钟前
EasyExcel篇
java·excel
DokiDoki之父1 小时前
多线程—飞机大战排行榜功能(2.0版本)
android·java·开发语言
高山上有一只小老虎1 小时前
走方格的方案数
java·算法
whatever who cares1 小时前
Java 中表示数据集的常用集合类
java·开发语言
JavaArchJourney2 小时前
TreeMap 源码分析
java
whitepure2 小时前
万字详解Java中的IO及序列化
java·后端
还梦呦2 小时前
2025年09月计算机二级Java选择题每日一练——第一期
java·开发语言
黑客影儿2 小时前
黑客哲学之学习笔记系列(三)
笔记·学习·程序人生·安全·职场和发展·网络攻击模型·学习方法