Java不可重复单列集合

Set集合

Java中的Set集合是一种无序、不重复的数据结构,用于存储唯一的元素。

Set集合的特点主要包括:

  1. 唯一性:Set不允许包含重复的元素,每个元素在集合中都是唯一的。
  2. 无序性:Set集合中的元素是无序的,即元素的存入和取出顺序不一定相同。
  3. 空元素:某些Set实现(如HashSet)允许包含空元素。

此外,在实际使用中,可以通过以下几种方式创建和初始化Set集合:

  1. 使用HashSet类:这是Set接口的一个常见实现,它基于哈希表来存储元素,因此具有良好的存取性能。
  2. 使用TreeSet类:这是另一个Set接口的实现,它基于红黑树数据结构,能够确保元素按照自然顺序或者自定义顺序排序。
  3. 使用LinkedHashSet类:这个实现保留了插入顺序,即迭代时元素的顺序与插入顺序一致。

TreeSet

Java中的TreeSet类是Set接口的实现之一,它使用红黑树(Red-Black tree)数据结构来存储元素。与HashSet不同,TreeSet能够确保集合中的元素处于排序状态。

以下是TreeSet的一些主要特点:

  1. 有序性TreeSet中的元素会根据其自然顺序进行排序,或者根据创建TreeSet时提供的Comparator进行排序。
  2. 唯一性:和所有Set实现一样,TreeSet不允许重复元素。
  3. 空元素TreeSet允许包含null元素。
  4. 高性能操作TreeSet提供了高效的插入、删除和查找操作,这些操作的时间复杂度通常为O(log n)。
  5. 可迭代:可以通过迭代器遍历TreeSet中的元素。

下面是一个简单的示例,展示如何使用TreeSet

import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        // 创建一个TreeSet实例
        TreeSet<Integer> numbers = new TreeSet<>();

        // 添加元素到TreeSet
        numbers.add(5);
        numbers.add(3);
        numbers.add(1);
        numbers.add(4);
        numbers.add(2);

        // 输出TreeSet中的元素(已排序)
        System.out.println("TreeSet中的元素(已排序): " + numbers);

        // 检查某个元素是否在TreeSet中
        if (numbers.contains(3)) {
            System.out.println("3 存在于TreeSet中");
        } else {
            System.out.println("3 不在TreeSet中");
        }

        // 移除一个元素
        numbers.remove(3);

        // 再次输出TreeSet中的元素
        System.out.println("移除3后的TreeSet: " + numbers);

        // 使用迭代器遍历TreeSet
        System.out.println("使用迭代器遍历TreeSet:");
        for (Integer number : numbers) {
            System.out.println(number);
        }
    }
}

在这个例子中,我们首先创建了一个TreeSet实例,然后向其中添加了一些整数。由于TreeSet是有序的,所以当我们打印集合的内容时,可以看到元素已经按照升序排列。我们还演示了如何检查元素是否存在于TreeSet中,如何删除元素,以及如何使用迭代器遍历集合。

如果你想要按照自定义的顺序对TreeSet中的元素进行排序,你可以在创建TreeSet时提供一个Comparator。例如:

import java.util.Comparator;
import java.util.TreeSet;

public class CustomSortedTreeSet {
    public static void main(String[] args) {
        // 创建一个自定义比较器的TreeSet实例
        TreeSet<String> sortedNames = new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o2.compareTo(o1); // 降序排序
            }
        });

        // 添加元素到TreeSet
        sortedNames.add("Alice");
        sortedNames.add("Bob");
        sortedNames.add("Charlie");

        // 输出TreeSet中的元素(按自定义顺序排序)
        System.out.println("自定义排序的TreeSet:" + sortedNames);
    }
}

在这个例子中,我们创建了一个TreeSet,并提供了一个自定义的Comparator来实现降序排序。当添加元素并打印结果时,你会看到元素是按照字母降序排列的。

HashSet

Java中的HashSet是一种实现了Set接口的无序集合,它使用哈希表来存储元素

HashSet的特点主要包括:

  1. 唯一性:HashSet不允许重复的元素,确保集合中的元素是唯一的。
  2. 无序性:HashSet不保证元素的迭代顺序,即元素在集合中的排列没有特定的顺序。
  3. 空元素:与某些其他集合实现不同,HashSet允许包含null元素。
  4. 性能:由于基于哈希表,HashSet提供了常数时间的性能,即add、remove和contains等操作通常具有O(1)的时间复杂度。

在实际使用中,HashSet可以通过以下方式创建和初始化:

  1. 默认构造函数HashSet()创建一个初始容量为16的HashSet。
  2. 指定初始容量HashSet(int initialCapacity)根据指定的初始容量创建HashSet。
  3. 指定初始容量和加载因子HashSet(int initialCapacity, float loadFactor)根据指定的初始容量和加载因子创建HashSet。
  4. 通过集合创建HashSet(Collection<? extends E> c)根据提供的集合创建HashSet,其中所有元素都会被添加到新创建的HashSet中。
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class HashSetExample {
    public static void main(String[] args) {
        // 创建一个HashSet实例
        Set<String> set = new HashSet<>();

        // 添加元素到HashSet
        set.add("Apple");
        set.add("Banana");
        set.add("Orange");

        // 输出HashSet中的元素
        System.out.println("HashSet中的元素:" + set);

        // 检查某个元素是否在HashSet中
        if (set.contains("Banana")) {
            System.out.println("Banana 存在于HashSet中");
        } else {
            System.out.println("Banana 不在HashSet中");
        }

        // 移除一个元素
        set.remove("Banana");

        // 再次输出HashSet中的元素
        System.out.println("移除Banana后的HashSet:" + set);

        // 使用迭代器遍历HashSet
        System.out.println("使用迭代器遍历HashSet:");
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()) {
            String element = iterator.next();
            System.out.println(element);
        }
    }
}

扩展——泛型

ava中的泛型是一种允许在编译时进行类型检查的强类型系统。它提供了一种方式来指定方法、接口或类可以使用不同类型的参数化版本,同时保持类型安全。

以下是关于Java泛型的一些要点:

  1. 类型参数声明:泛型方法或类在声明时会有一个类型参数部分,通常由尖括号<>包围,例如public class Box<T>public static <E> void sort(E[] array)。这里的TE是类型参数,它们代表某种类型,这个类型在实例化或调用方法时被确定。
  2. 类型安全:泛型的主要目的是提供编译时的类型安全检查。这意味着如果你尝试将错误的类型传递给泛型方法或使用泛型类,编译器会生成错误,而不是等到运行时才检测到类型错误。
  3. 类型擦除:在Java中,泛型信息在编译后会被擦除,这个过程称为类型擦除。这是因为Java泛型是基于类型的擦除来实现的,以确保与旧版本的Java代码兼容。
  4. 通配符:在泛型中,通配符?用来表示未知类型。这在你需要编写可以处理未知类型参数的方法时非常有用。例如,List<?>表示一个列表,其元素类型未知。
  5. 边界:泛型还可以有边界,用来限制可以接受的类型参数的范围。例如,public class Animal {} public class Dog extends Animal {} public class Box<T extends Animal>这里T被限制为必须是Animal类或其子类。
  6. 泛型方法:泛型方法是一种可以处理不同类型参数的方法。例如,public static <E> void sort(E[] array)是一个泛型方法,它可以对任何类型的数组进行排序。
  7. 泛型类:泛型类允许你创建可以处理不同类型参数的类的实例。例如,Box<String> box = new Box<>();这里Box是一个泛型类,它的类型参数是String

 泛型类

Java泛型类是一种允许在类级别上参数化的编程技术,它提供了编译时类型检查的安全性和代码的重用性

以下是一些关于Java泛型类的关键点:

  1. 类型参数:泛型类使用类型参数来定义它可以操作的类型。例如,List<T>中的T就是一个类型参数,表示列表可以存储任意类型的对象。
  2. 类型安全性:泛型的主要目的是提高代码的类型安全性。通过在编译时检查类型,可以避免在运行时进行类型转换和类型检查,从而减少错误和提高效率。
  3. 可读性和可维护性:使用泛型可以让代码更加清晰和易于理解,因为类型信息是明确的,这有助于其他开发者阅读和维护代码。
  4. 灵活性和重用性:泛型类可以用于多种类型,而不是仅限于单一的类型。这意味着你可以重用相同的代码来处理不同的数据类型,而不需要为每种类型编写单独的类或方法。
  5. 有界类型参数:泛型类可以限制类型参数的范围。例如,你可以声明一个泛型类List<T extends Number>,这样只有Number类及其子类才能作为类型参数使用。
  6. 通配符:泛型还支持通配符,如?extendssuper关键字,这些可以用来进一步细化或放宽类型参数的限制。
  7. 泛型方法:除了泛型类,还可以定义泛型方法。泛型方法允许在方法级别上指定类型参数,这使得即使在非泛型类中也可以利用泛型的 type 安全特性。
  8. Class与泛型:在运行时,由于类型擦除,泛型信息是不可用的。但是,可以通过Class对象的getTypeParameters方法来获取泛型类的类型参数信息,这在某些情况下可能是有用的。
  9. 限制和问题:虽然泛型提供了很多好处,但它们也有一些限制和需要注意的问题,比如不能创建泛型数组T[],以及泛型类型不能被继承等。
  10. 与通配符的关系:泛型和通配符虽然都用于处理类型参数,但它们的用途和行为有所不同。泛型提供了更严格的类型控制,而通配符则提供了更大的灵活性。

代码展示:

public class Box<T> {
    private T item;

    public void setItem(T item) {
        this.item = item;
    }

    public T getItem() {
        return item;
    }

    public static void main(String[] args) {
        Box<String> stringBox = new Box<>();
        stringBox.setItem("Hello");
        String str = stringBox.getItem();
        System.out.println("String item: " + str);

        Box<Integer> intBox = new Box<>();
        intBox.setItem(123);
        Integer num = intBox.getItem();
        System.out.println("Integer item: " + num);
    }
}

泛型方法

Java泛型方法是一种在方法级别上使用泛型技术的方法,它允许方法接受不同类型的参数并返回不同类型的值。以下是关于Java泛型方法的一些关键点:

  1. 类型参数定义:泛型方法通过在方法返回类型之前加上尖括号<T>来定义类型参数,其中T是一个类型参数,可以是任意合法的Java标识符。这允许方法在调用时接受不同的类型参数。
  2. 可变参数和返回值:泛型方法可以接受可变长度的参数,并且可以返回一个与传入参数类型相同的值。例如,public static <T> T getMiddle(T... a)方法接受一个泛型数组,并返回数组中间的元素。
  3. 类型参数的使用:在方法体内,可以使用类型参数T来定义变量、返回值类型或者作为其他方法的参数类型。这提供了一种灵活的方式来处理不同类型的数据,而不需要为每种类型编写单独的方法。
  4. 类型擦除:与泛型类一样,泛型方法的类型信息在运行时也会被擦除,因此不能在运行时直接获取到具体的类型参数。但是,这并不影响泛型方法在编译时提供的类型安全性。
  5. 限制类型参数:可以在泛型方法中使用extends关键字来限制类型参数的范围,例如public static <T extends Number> T getFirstElement(List<T> list),这样只有Number类及其子类才能作为类型参数使用。
  6. 方法重载:泛型方法和非泛型方法可以进行重载,但需要注意的是,泛型方法的重载规则与普通方法相同,即方法签名必须不同才能进行重载。
  7. 通配符的使用:在泛型方法中也可以使用通配符?extendssuper关键字来进一步细化或放宽类型参数的限制,提供了更大的灵活性。
import java.util.ArrayList;
import java.util.List;

public class GenericExample {
    public static void main(String[] args) {
        // 创建一个泛型类实例
        MyGenericClass<String> myGenericClass = new MyGenericClass<>();
        myGenericClass.setValue("Hello, World!");
        System.out.println(myGenericClass.getValue());

        // 创建一个泛型方法实例
        MyGenericMethod myGenericMethod = new MyGenericMethod();
        List<Integer> numbers = new ArrayList<>();
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);
        System.out.println(myGenericMethod.getMiddle(numbers));
    }
}

// 泛型类示例
class MyGenericClass<T> {
    private T value;

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}

// 泛型方法示例
class MyGenericMethod {
    public <T extends Number> T getMiddle(List<T> list) {
        if (list == null || list.isEmpty()) {
            return null;
        }
        int middleIndex = list.size() / 2;
        return list.get(middleIndex);
    }
}
  • 25
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java中,有多种单列集合可供使用。其中一些常见的单列集合包括: - ArrayList:ArrayList是基于数组实现的动态数组,可以根据需要自动扩展容量。它允许存储重复元素,并且可以按索引访问元素。 - LinkedList:LinkedList是基于链表实现的集合,它可以高效地进行插入和删除操作。与ArrayList相比,LinkedList在随机访问方面性能较差,但在插入和删除操作方面更加高效。 - HashSet:HashSet是基于哈希表实现的集合,它不允许存储重复元素,并且不保证元素的顺序。HashSet提供了常数时间的插入、删除和查找操作。 - TreeSet:TreeSet是基于红黑树实现的有序集合,它按照元素的自然顺序进行排序,或者根据提供的Comparator进行排序。TreeSet不允许存储重复元素。 - LinkedHashSet:LinkedHashSet是基于哈希表和链表实现的有序集合,它按照元素插入的顺序进行排序。LinkedHashSet允许存储重复元素。 - PriorityQueue:PriorityQueue是基于优先级堆实现的队列,它根据元素的优先级进行排序。PriorityQueue允许存储重复元素,并且提供了常数时间的插入和删除最小元素的操作。 以上是一些常见的单列集合,每种集合都有其特定的用途和适用场景。具体选择哪种集合取决于你的需求和性能要求。 #### 引用[.reference_title] - *1* *2* *3* [Java中Collection单列集合](https://blog.csdn.net/m0_60489526/article/details/119830185)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值