Java集合-List讲解

目录

Java 集合框架(Collections Framework)是 Java 中用于 存储和操作数据组的重要架构 。它提供了一组接口、实现类和算法。

一、集合框架层次结构

复制代码
Collection (接口)
├── List (接口 - 有序,可重复)
│   ├── ArrayList (实现类)
│   ├── LinkedList (实现类)
│   ├── Vector (线程安全,已过时)
│   └── Stack (继承Vector)
│
├── Set (接口 - 无序,不可重复)
│   ├── HashSet (实现类)
│   │   └── LinkedHashSet (保持插入顺序)
│   ├── SortedSet (接口)
│   │   └── TreeSet (实现类)
│   └── EnumSet (专用于枚举)
│
└── Queue (接口 - 队列)
    ├── Deque (双端队列接口)
    │   ├── ArrayDeque (实现类)
    │   └── LinkedList (也实现了Deque)
    │
    ├── PriorityQueue (优先队列)
    └── BlockingQueue (阻塞队列接口)
        ├── ArrayBlockingQueue
        ├── LinkedBlockingQueue
        └── PriorityBlockingQueue

Map (接口 - 键值对)
├── HashMap (实现类)
│   └── LinkedHashMap (保持插入顺序)
├── TreeMap (基于红黑树)
├── Hashtable (线程安全,已过时)
├── WeakHashMap (弱引用)
└── ConcurrentHashMap (并发版)

Java集合大致可以分为两大体系,一个是Collection,另一个是Map

  • Collection :主要由ListSetQueue接口组成,List代表有序、重复的集合;其中Set代表无序、不可重复的集合;Queue体系集合,代表一种队列集合实现。
  • Map:则代表具有映射关系的键值对集合。
    java.util.Collection下的接口和继承类关系简易结构图:

    java.util.Map下的接口和继承类关系简易结构图:

其中,Java 集合框架中主要封装的是典型的数据结构和算法,如动态数组、双向链表、队列、栈、Set、Map 等。

二、Collection集合

通过集合的关系图我们可以知道Collection是集合的顶层父类,他定义了集合的基本方法如

基本操作方法

方法签名 功能描述 返回值 示例 时间复杂度
int size() 返回集合中元素的数量 元素个数 list.size()3 O(1)
boolean isEmpty() 判断集合是否为空 true/false list.isEmpty()false O(1)
boolean contains(Object o) 判断是否包含指定元素 true/false list.contains("A")true List: O(n) Set: O(1) TreeSet: O(log n)
boolean add(E e) 添加元素到集合 是否成功 list.add("D")true ArrayList: 均摊O(1) LinkedList: O(1) TreeSet: O(log n)
boolean remove(Object o) 移除指定元素 是否成功 list.remove("A")true ArrayList: O(n) LinkedList: O(n) HashSet: O(1)

批量操作方法

方法签名 功能描述 返回值 示例 说明
boolean containsAll(Collection<?> c) 是否包含集合c中所有元素 true/false list.containsAll(subList) 检查子集关系
boolean addAll(Collection<? extends E> c) 添加集合c中所有元素 是否改变 list.addAll(anotherList) 批量添加
boolean removeAll(Collection<?> c) 移除集合c中所有元素 是否改变 list.removeAll(toRemove) 差集操作
boolean retainAll(Collection<?> c) 仅保留集合c中元素 是否改变 list.retainAll(common) 交集操作
void clear() 清空集合所有元素 list.clear() 集合变为空

转换和迭代方法

方法签名 功能描述 返回值 示例 说明
Object[] toArray() 转换为Object数组 Object数组 list.toArray() 返回新数组
<T> T[] toArray(T[] a) 转换为指定类型数组 指定类型数组 list.toArray(new String[0]) 类型安全转换
Iterator<E> iterator() 返回迭代器 Iterator对象 list.iterator() 用于遍历集合
default boolean removeIf(Predicate<? super E> filter) 条件删除 是否改变 list.removeIf(s -> s.length() > 3) Java 8+
default Spliterator<E> spliterator() 返回分割迭代器 Spliterator对象 list.spliterator() Java 8+,并行遍历
default Stream<E> stream() 返回顺序流 Stream对象 list.stream() Java 8+,流操作
default Stream<E> parallelStream() 返回并行流 Stream对象 list.parallelStream() Java 8+,并行流操作

集合运算方法

方法 数学运算 示意图 示例
addAll() 并集 A ∪ B A.addAll(B)
retainAll() 交集 A ∩ B A.retainAll(B)
removeAll() 差集 A - B A.removeAll(B)

常见操作示例

操作需求 代码示例 说明
遍历集合 for (E e : collection) { ... } 增强for循环
安全遍历并删除 iterator.remove() 使用迭代器删除
转换为数组 String[] arr = coll.toArray(new String[0]) 推荐写法
批量添加元素 coll.addAll(Arrays.asList("A","B","C")) 初始化集合
过滤集合 coll.removeIf(e -> e.startsWith("A")) Java 8+
集合判空 if (!coll.isEmpty()) { ... } 优于size() > 0

注意事项表格

方法 注意事项 推荐做法
contains() 依赖equals()hashCode() 正确实现这两个方法
remove(Object) 只删除第一个匹配项 使用removeIf()删除所有
toArray() 无参方法返回Object[] 使用带参方法指定类型
addAll() 可能修改原集合 注意并发修改异常
clear() 不释放元素引用 大集合考虑设为null
iterator() 遍历时不能修改集合 使用迭代器的remove()
场景 建议 理由
频繁包含检查 使用HashSet O(1)时间复杂度
频繁插入删除 使用LinkedList 首尾操作O(1)
随机访问 使用ArrayList O(1)索引访问
需要排序 使用TreeSet 自动维护顺序
线程安全 使用并发集合 ConcurrentHashMap
只读操作 使用不可变集合 Collections.unmodifiableXXX()

Collection集合中所包含的方法:

java 复制代码
public interface Collection<E> extends Iterable<E> {
    // 基本操作方法
    int size();
    boolean isEmpty();
    boolean contains(Object o);
    boolean add(E e);
    boolean remove(Object o);
    
    // 批量操作
    boolean containsAll(Collection<?> c);
    boolean addAll(Collection<? extends E> c);
    boolean removeAll(Collection<?> c);
    boolean retainAll(Collection<?> c);
    void clear();
    
    // 数组转换
    Object[] toArray();
    <T> T[] toArray(T[] a);
    
    // 迭代器
    Iterator<E> iterator();
    
    // Java 8 新增方法
    default boolean removeIf(Predicate<? super E> filter) { ... }
    default Spliterator<E> spliterator() { ... }
    default Stream<E> stream() { ... }
    default Stream<E> parallelStream() { ... }
}

1.List集合

List集合的特点就是存取有序,可以存储重复的元素,可以用下标进行元素的操作

该类适用于多线程读多写少并发场景,它在有写操作的时候会copy一份数据,然后写完再设置成新的数据,同时也进行了重入锁的处理保证了安全。

1.CopyOnWriteArrayList

CopyOnWriteArrayListJava 并发包中的线程安全 List 实现,采用 "写时复制" 策略

读操作:

java 复制代码
// 直接读取,无需加锁
public E get(int index) {
    return get(getArray(), index);  // 直接访问当前数组
}

写操作:

java 复制代码
// 修改操作(add/set/remove)
public boolean add(E e) {
    synchronized (lock) {  // 写操作加锁
        Object[] elements = getArray();
        int len = elements.length;
        
        // 1. 创建新数组(长度+1)
        Object[] newElements = Arrays.copyOf(elements, len + 1);
        
        // 2. 在新数组上修改
        newElements[len] = e;
        
        // 3. 替换引用
        setArray(newElements);
        
        return true;
    }
}

2、ArrayList

它是一个标准的集合实现类,特点为有序,可重复,存储是连续的,因此查询较快,增删较为慢,使用Object数组进行存储。
ArrayList 是 Java 中最常用的动态数组实现,基于数组实现,支持动态扩容
ArrayList底层实现:

java 复制代码
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    
    // 默认初始容量
    private static final int DEFAULT_CAPACITY = 10;
    
    // 存储元素的数组
    transient Object[] elementData; // non-private to simplify nested class access
    
    // 当前元素数量
    private int size;
    
    // 空数组实例(用于空列表)
    private static final Object[] EMPTY_ELEMENTDATA = {};
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
}

核心特性

特性 说明
数据结构 基于数组
扩容机制 增长因子为 1.5 倍
随机访问 O(1) 时间复杂度
插入/删除 O(n) 时间复杂度(平均)
线程安全 非线程安全
内存连续 连续内存分配
允许元素 允许 null 值,允许重复元素

构造方法

java 复制代码
// 1. 默认构造(延迟初始化)
ArrayList<String> list1 = new ArrayList<>();  // 初始容量为0,第一次add时扩容到10

// 2. 指定初始容量
ArrayList<String> list2 = new ArrayList<>(100);  // 初始容量100

// 3. 从其他集合构造
List<String> existingList = Arrays.asList("A", "B", "C");
ArrayList<String> list3 = new ArrayList<>(existingList);

扩容过程

java 复制代码
// add() 方法中的扩容逻辑
public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // 确保容量足够
    elementData[size++] = e;
    return true;
}

private void ensureCapacityInternal(int minCapacity) {
    // 如果是空数组,使用默认容量10
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    ensureExplicitCapacity(minCapacity);
}

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;  // 修改计数++
    
    // 需要扩容
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

// 核心扩容方法
private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);  // 增长1.5倍
    
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    
    // 创建新数组并拷贝数据
    elementData = Arrays.copyOf(elementData, newCapacity);
}

常用方法详解

1. 添加元素

java 复制代码
ArrayList<String> list = new ArrayList<>();

// 末尾添加
list.add("A");          // ["A"]
list.add("B");          // ["A", "B"]

// 指定位置插入
list.add(1, "C");       // ["A", "C", "B"]  O(n)操作

// 批量添加
list.addAll(Arrays.asList("D", "E"));  // ["A", "C", "B", "D", "E"]

// 指定位置批量添加
list.addAll(2, Arrays.asList("X", "Y")); // ["A", "C", "X", "Y", "B", "D", "E"]

2. 访问元素

java 复制代码
ArrayList<String> list = new ArrayList<>(Arrays.asList("A", "B", "C", "D"));

// 获取元素(随机访问 O(1))
String first = list.get(0);   // "A"
String last = list.get(list.size() - 1);  // "D"

// 遍历元素
for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}

// 增强for循环
for (String item : list) {
    System.out.println(item);
}

// Java 8+ forEach
list.forEach(System.out::println);

// 迭代器遍历
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

3. 修改元素

java 复制代码
ArrayList<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));

// 设置元素(替换)
list.set(1, "BB");  // ["A", "BB", "C"]

// 批量替换(Java 8+)
list.replaceAll(s -> s + "!");  // ["A!", "BB!", "C!"]

// 排序
list.sort(String::compareTo);  // 自然排序
list.sort(Comparator.reverseOrder());  // 逆序
Collections.sort(list);  // 传统方式

// 洗牌(随机打乱)
Collections.shuffle(list);

4. 删除元素

java 复制代码
ArrayList<String> list = new ArrayList<>(
    Arrays.asList("A", "B", "C", "D", "E", "B")
);

// 按索引删除(返回被删除元素)
String removed = list.remove(2);  // 删除 "C",返回 "C"

// 按元素删除(删除第一个匹配项)
boolean success = list.remove("B");  // 删除第一个 "B",返回 true
list.remove("X");  // 元素不存在,返回 false

// 批量删除
list.removeAll(Arrays.asList("D", "E"));  // 删除所有匹配项

// 条件删除(Java 8+)
list.removeIf(s -> s.startsWith("A"));  // 删除所有以A开头的元素

// 保留指定元素(交集)
list.retainAll(Arrays.asList("B", "C"));  // 只保留 B 和 C

// 清空
list.clear();  // 清空所有元素

5. 查找元素

java 复制代码
ArrayList<String> list = new ArrayList<>(
    Arrays.asList("A", "B", "C", "B", "D")
);

// 查找索引
int firstIndex = list.indexOf("B");     // 1
int lastIndex = list.lastIndexOf("B");  // 3
int notFound = list.indexOf("X");       // -1

// 判断包含
boolean containsB = list.contains("B");  // true
boolean containsAll = list.containsAll(Arrays.asList("A", "C"));  // true

// 查找条件匹配(Java 8+)
Optional<String> firstMatch = list.stream()
    .filter(s -> s.length() > 1)
    .findFirst();

boolean anyMatch = list.stream().anyMatch(s -> s.equals("B"));
boolean allMatch = list.stream().allMatch(s -> s != null);

3、LinkedList

LinkedList 是 Java 中基于双向链表实现List,同时也实现了 Deque 接口,可以作为队列使用。

与其他的实现类不同,他的底层是采用链接形式存储的,因此增删块,查询较慢如:

节点结构

java 复制代码
private static class Node<E> {
    E item;          // 存储的元素
    Node<E> next;    // 后继节点
    Node<E> prev;    // 前驱节点
    
    Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}

链表结构

java 复制代码
public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable {
    
    transient int size = 0;          // 链表大小
    transient Node<E> first;         // 头节点
    transient Node<E> last;          // 尾节点
    
    // 节点关系示意图:
    // first ←→ node1 ←→ node2 ←→ ... ←→ last
    //   ↑         ↑         ↑               ↑
    // prev=null prev=first prev=node1    prev=...
    // next=node1 next=node2 next=node3   next=null
}

核心特性

特性 说明
数据结构 双向链表
内存分配 非连续内存
随机访问 O(n) 时间复杂度
插入/删除 O(1) 时间复杂度(已知节点位置)
头尾操作 O(1) 时间复杂度
线程安全 非线程安全
允许元素 允许 null 值,允许重复元素
额外空间 每个元素需要存储前后指针

构造方法

java 复制代码
// 1. 默认构造(空链表)
LinkedList<String> list1 = new LinkedList<>();

// 2. 从其他集合构造
List<String> existingList = Arrays.asList("A", "B", "C");
LinkedList<String> list2 = new LinkedList<>(existingList);

// 创建后结构:
// first → Node("A") ↔ Node("B") ↔ Node("C") ← last
// size = 3

1. 添加元素

java 复制代码
LinkedList<String> list = new LinkedList<>();

// 添加到末尾(List接口)
list.add("A");           // [A]
list.add("B");           // [A, B]

// 指定位置插入
list.add(1, "C");        // [A, C, B]

// 添加到末尾(等价于add)
list.addLast("D");       // [A, C, B, D]

// 添加到开头
list.addFirst("Z");      // [Z, A, C, B, D]

// 批量添加
list.addAll(Arrays.asList("E", "F"));  // [Z, A, C, B, D, E, F]

2. 访问元素

java 复制代码
LinkedList<String> list = new LinkedList<>(
    Arrays.asList("A", "B", "C", "D", "E")
);

// 获取头尾元素
String first = list.getFirst();  // "A"
String last = list.getLast();    // "E"

// 按索引获取(需要遍历)
String third = list.get(2);      // "C" - 从头开始遍历

// 遍历方式
for (int i = 0; i < list.size(); i++) {  // ❌ 低效:每次get都是O(n)
    System.out.println(list.get(i));
}

// ✅ 推荐:迭代器遍历
for (String item : list) {  // 使用迭代器,O(n)总体
    System.out.println(item);
}

// ✅ 推荐:列表迭代器(可双向遍历)
ListIterator<String> iterator = list.listIterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}
// 反向遍历
while (iterator.hasPrevious()) {
    System.out.println(iterator.previous());
}

3. 查找元素

java 复制代码
LinkedList<String> list = new LinkedList<>(
    Arrays.asList("A", "B", "C", "B", "D")
);

// 查找索引(从头开始遍历)
int firstIndex = list.indexOf("B");     // 1
int lastIndex = list.lastIndexOf("B");  // 3

// 判断包含
boolean hasA = list.contains("A");      // true

// 查找条件匹配(Java 8+)
Optional<String> result = list.stream()
    .filter(s -> s.startsWith("C"))
    .findFirst();

4. 删除元素

java 复制代码
LinkedList<String> list = new LinkedList<>(
    Arrays.asList("A", "B", "C", "D", "E")
);

// 删除头节点
String removedFirst = list.removeFirst();  // "A"
String polledFirst = list.pollFirst();     // "B"(队列风格)

// 删除尾节点
String removedLast = list.removeLast();    // "E"
String polledLast = list.pollLast();       // "D"

// 按索引删除(需要遍历到该位置)
String removed = list.remove(0);           // "C"

// 按元素删除(删除第一个匹配项)
boolean success = list.remove("B");        // false("B"已不存在)

// 清空
list.clear();  // first = last = null, size = 0

4、Vector

该类于JDK1.1就出现了,特点为:线程安全但是效率较慢因为他的方法大多采用synchronized进行修饰,也是采用Object数组进行存储
底层数据结构

java 复制代码
public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    
    // 存储元素的数组
    protected Object[] elementData;
    
    // 元素数量
    protected int elementCount;
    
    // 容量增长系数(扩容时使用)
    protected int capacityIncrement;
    
    // 默认初始容量
    private static final int DEFAULT_CAPACITY = 10;
}

核心特性

特性 Vector ArrayList 说明
线程安全 ✅ 是(synchronized) ❌ 否 Vector 的主要特点
数据结构 动态数组 动态数组 底层都是数组
扩容机制 可指定增长量,默认2倍 固定1.5倍 Vector 更灵活
性能 较慢(锁开销) 较快 Vector 有同步开销
迭代器 快速失败 快速失败 都支持 fail-fast
遗留类 ✅ 是(JDK 1.0) ❌ 否(JDK 1.2) Vector 已过时

构造方法

java 复制代码
// 1. 默认构造(容量10,满时容量翻倍)
Vector<String> vec1 = new Vector<>();  

// 2. 指定初始容量
Vector<String> vec2 = new Vector<>(100);  

// 3. 指定初始容量和容量增长量
Vector<String> vec3 = new Vector<>(100, 20);  
// 初始容量100,每次扩容增加20

// 4. 从集合构造
List<String> list = Arrays.asList("A", "B", "C");
Vector<String> vec4 = new Vector<>(list);

扩容逻辑

java 复制代码
// Vector 的扩容方法
private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    
    // 关键:如果有 capacityIncrement,按增量增长;否则翻倍
    int newCapacity = oldCapacity + 
        ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);
    
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    
    elementData = Arrays.copyOf(elementData, newCapacity);
}

扩容示例

java 复制代码
// 示例1:默认扩容(翻倍)
Vector<Integer> vec1 = new Vector<>(5);
// 初始容量:5
vec1.add(1); vec1.add(2); vec1.add(3); vec1.add(4); vec1.add(5);
vec1.add(6);  // 触发扩容:5 → 10(翻倍)

// 示例2:指定增量扩容
Vector<Integer> vec2 = new Vector<>(5, 3);
// 初始容量:5,增量:3
vec2.add(1); vec2.add(2); vec2.add(3); vec2.add(4); vec2.add(5);
vec2.add(6);  // 触发扩容:5 → 8(5+3)
vec2.add(7); vec2.add(8);
vec2.add(9);  // 触发扩容:8 → 11(8+3)

同步机制

java 复制代码
// Vector 的所有公共方法都加了 synchronized
public synchronized boolean add(E e) {
    modCount++;
    ensureCapacityHelper(elementCount + 1);
    elementData[elementCount++] = e;
    return true;
}

public synchronized E get(int index) {
    if (index >= elementCount)
        throw new ArrayIndexOutOfBoundsException(index);
    return elementData(index);
}

public synchronized E remove(int index) {
    modCount++;
    if (index >= elementCount)
        throw new ArrayIndexOutOfBoundsException(index);
    E oldValue = elementData(index);
    
    int numMoved = elementCount - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index, numMoved);
    
    elementData[--elementCount] = null; // 帮助GC
    return oldValue;
}

复合操作的线程安全问题

java 复制代码
// 即使单个方法是线程安全的,复合操作也可能有问题
Vector<String> vector = new Vector<>();

// ❌ 线程不安全:check-then-act 模式
if (!vector.isEmpty()) {          // 线程A检查
    String item = vector.get(0);  // 线程B可能在这里remove(0)
    // 可能抛出 IndexOutOfBoundsException
}

// ✅ 解决方案:对整个复合操作加锁
synchronized(vector) {
    if (!vector.isEmpty()) {
        String item = vector.get(0);
        // 安全操作
    }
}

// ❌ 另一个问题:迭代中的修改
for (int i = 0; i < vector.size(); i++) {
    String item = vector.get(i);  // size()和get()之间可能有其他线程修改
    process(item);
}

// ✅ 解决方案:迭代时加锁
synchronized(vector) {
    for (int i = 0; i < vector.size(); i++) {
        String item = vector.get(i);
        process(item);
    }
}

1. 容量管理方法

java 复制代码
Vector<String> vec = new Vector<>(10);

// 获取/设置容量
int capacity = vec.capacity();        // 当前容量:10
vec.ensureCapacity(100);              // 确保容量至少100
vec.trimToSize();                     // 修剪容量到当前大小

// 设置大小(可能截断或填充null)
vec.setSize(15);                      // 如果原来小于15,填充null
vec.setSize(5);                       // 如果原来大于5,截断后面元素

// 获取底层数组
Object[] array = vec.toArray();

2. 元素操作特有方法

java 复制代码
Vector<String> vec = new Vector<>(Arrays.asList("A", "B", "C", "D"));

// 添加元素(尾部)
vec.addElement("E");                  // 同add()
vec.insertElementAt("X", 2);          // 在索引2处插入

// 设置元素
vec.setElementAt("BB", 1);            // 设置索引1为"BB"

// 删除元素
vec.removeElement("B");               // 删除第一个"B"
vec.removeElementAt(0);               // 删除索引0元素
vec.removeAllElements();              // 清空所有元素

// 查找元素
int index = vec.indexOf("C");         // 查找索引
int lastIndex = vec.lastIndexOf("D"); // 从后往前查找
boolean contains = vec.contains("A"); // 是否包含

// 获取首尾元素
String first = vec.firstElement();    // 第一个元素
String last = vec.lastElement();      // 最后一个元素

3. 枚举器(Enumeration)

java 复制代码
Vector<String> vec = new Vector<>(Arrays.asList("A", "B", "C"));

// 获取枚举器(旧版迭代器)
Enumeration<String> enumeration = vec.elements();

// 遍历
while (enumeration.hasMoreElements()) {
    String element = enumeration.nextElement();
    System.out.println(element);
}

// 与Iterator对比
Iterator<String> iterator = vec.iterator();
while (iterator.hasNext()) {
    String element = iterator.next();
    System.out.println(element);
    iterator.remove();  // Enumeration没有remove方法
}
相关推荐
李白你好5 小时前
Bypass_Webshell webshell编码工具 支持 jsp net php asp编码免杀
开发语言·php
feifeigo1235 小时前
C#中实现控件拖动功能
开发语言·c#
曹牧5 小时前
C#:List<string>类型的集合转换成用逗号分隔的字符串
开发语言·c#·list
fengfuyao9855 小时前
基于C# WinForm的收银管理系统实现
开发语言·c#
05大叔5 小时前
苍穹外买Day05
java·开发语言
咘噜biu5 小时前
Java 安全的打印对象数据到日志
java·json·日志·脱敏
曹牧5 小时前
Eclipse 中 SVN 操作指南
java·svn·eclipse
Lv11770085 小时前
Visual Studio 中的 ArrayList数组 和 List数组
数据结构·笔记·c#·list·visual studio
阿里嘎多学长5 小时前
2025-12-15 GitHub 热点项目精选
开发语言·程序员·github·代码托管