Java高级编程-数据结构(个人学习记录)

1.枚举(Enumeration)

简要概述:枚举(Enumeration)接口虽然它本身不属于数据结构,但它在其他数据结构的范畴里应用很广。 枚举(The Enumeration)接口定义了一种从数据结构中取回连续元素的方式。

例如,枚举定义了一个叫nextElement 的方法,该方法用来得到一个包含多元素的数据结构的下一个元素。

Enumeration接口中定义了一些方法,通过这些方法可以枚举(一次获得一个)对象集合中的元素。

这种传统接口已被迭代器取代,虽然Enumeration 还未被遗弃,但在现代代码中已经被很少使用了。尽管如此,它还是使用在诸如Vector和Properties这些传统类所定义的方法中,除此之外,还用在一些API类,并且在应用程序中也广泛被使用。 下表总结了一些Enumeration声明的方法:

序号方法描述
1boolean hasMoreElements( ) 测试此枚举是否包含更多的元素。
2Object nextElement( ) 如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素。

Enumeration接口是在早期Java集合框架中提供的一个遍历集合元素的迭代器,它可以用来逐一获取集合中的每个元素并考虑到循环结束时所需要采取的操作。

其语法如下:

public interface Enumeration<E> {
    boolean hasMoreElements();
    E nextElement();
}

其中,hasMoreElements()函数方法检查枚举是否还有更多的元素;

nextElement()函数方法返回具体的枚举对象的下一个对象。

对于这个接口,需要注意以下几点:

  • 该接口功能单一,只能一次性地向前遍历容器内的元素。与之相反的是Iterator迭代器接口。

  • Enumeration和 Iterator 在实现方式、其结果和工作机制上都不相同。

  • 该接口已被JDK 1.0/J2SE 1.2 中的 Iterator 接口所替换,所以尽量使用 java.util.Iterator 接口执行类似任务。

总之,如果要进行遍历Collection或Vector类型衰减口,最好使用Iterator类。这个类具有许多优点,为您提供更大的灵活性,并让代码读起来更加简洁。


2.位集合(BitSet)

简要概述:一个Bitset类创建一种特殊类型的数组来保存位值。BitSet中数组大小会随需要增加。这和位向量(vector of bits)比较类似。

这是一个传统的类,但它在Java 2中被完全重新设计。

BitSet定义了两个构造方法。

第一个构造方法创建一个默认的对象:

BitSet()

第二个方法允许用户指定初始大小。所有位初始化为0。

BitSet(int size)

BitSet中实现了Cloneable接口中定义的常用方法如下表所列:

Java中的位集合(BitSet)是一个特殊的数组,其只包含0或1两种值。之所以它被称为位集合,是因为它使用每个元素的二进制位来表示是否存在某个值,而不是使用单独的元素。

具体来说,BitSet类允许我们进行3种操作:

  • 获取:通过get(int index)方法检查bitset中特定位置是否设置。

  • 设置:通过set(int index)方法将bitset中给定位设置为true或1。

  • 清除:通过clear(int index)方法将bitset中给定位设置为false或0。

另外,也可以通过clear()方法来清空所有位。通常情况下,BitSet用于不重复地存储一组标志并使用位运算对它们进行操作。

以下是BitSet类的基本语法:

import java.util.BitSet;
 
public class BitSetExample {
    public static void main(String[] args) {
        // Create a new BitSet
        BitSet bs = new BitSet(8);
 
        // Set some bits
        bs.set(2);
        bs.set(4);
        bs.set(7);
 
        // Print the BitSet
        System.out.println("Initial BitSet: " + bs);
 
        // Clear 4th bit
        bs.clear(4);
 
        // Print the BitSet
        System.out.println("After clear(4): " + bs);
    }
}

输出结果如下:

Initial BitSet: {2, 4, 7}
After clear(4): {2, 7}

在上述示例中,我们创建了一个包含8位的 BitSet 对象。随后,我们设置一些位(第2、4和7位)并打印出初始状态的BitSet。接着,我们清除了第4位。最终,我们再次打印BitSet以验证其已被成功清除。

需要注意的是,因为 Java BitSet 是一种将位作为“是否存在”标志的实现方式,所以不适用于给定位置上存在不同数据类型值的集合。

如果需要表示集合,Java 5之后提供了更强大的实现方式——BitSet类的替代方案:EnumSet和HashSet。它们都具有更严格的类型限制,并且能够比 BitSet 更好地保证代码安全性。

  • EnumSet: 推荐用于枚举类型元素

  • HashSet: 适合处理不同类型元素

与BitSet相比,这些类的主要优点是:

  • 强类型检查确保只允许特定类型的元素在集合中存在

  • 可支持各种操作,如向集合添加或删除元素。

  • 可透明地调整内部实现以最大程度地提高性能

总而言之,位集合(BitSet)虽然可以满足我们初学的需求,但是对于目前的版本来说,除非有特殊需求,建议使用EnumSet、HashSet等新的类型安全的集合实现类,因为 Bitset 类型过于占空间以及过于占用内存,性能表现上较为低效。


3.向量 (Vector)

简要概述:Vector 类实现了一个动态数组。和与ArrayList 很相似,但两者是不同的:

  • Vector 是同步访问的,线程安全的。

  • Vector 包含了许多传统的方法,这些方法不属于集合框架。

向量(Vector)类和传统数组非常相似,但是Vector的大小能根据需要动态的变化。

和数组一样,Vector对象的元素也能通过索引访问。

使用Vector类最主要的好处就是在创建对象的时候不必给对象指定大小,它的大小会根据需要动态的变化。

Vector 主要用在事先不知道数组的大小,或者只是需要一个可以改变大小的数组的情况。

Vector 类支持 4 种构造方法。

第一种构造方法创建一个默认的向量,默认大小为 10:

Vector()

第二种构造方法创建指定大小的向量。

Vector(int size)

第三种构造方法创建指定大小的向量,并且增量用 incr 指定。增量表示向量每次增加的元素数目。

Vector(int size,int incr)

第四种构造方法创建一个包含集合 c 元素的向量:

Vector(Collection c)

在Java语言中,如果使用的是Vector类,则可以通过调用其成员函数elements()方法来获取一个枚举对象。此枚举遍历该向量的组件。它返回元素类型的 Object而不是当前标准集合框架中常用的泛型。

以下是使用Vector中的elements()方法的示例代码:

import java.util.Vector;
import java.util.Enumeration;
​
class VectorExample {
    public static void main(String[] args) {
        Vector<String> vector = new Vector<String>(4);
        vector.add("Apple");
        vector.add("Banana");
        vector.add("Orange");
        vector.add("Grapes");
 
        // Get the Enumeration object
        Enumeration<String> e = vector.elements();
 
        // Traverse through the elements of Vector
        while (e.hasMoreElements())
            System.out.println(e.nextElement());
    }
}

该代码片段会打印输出以下内容:

Apple
Banana
Orange
Grapes

注意:Vector已经被Java官方推荐的ArrayList取代作为一种更好的集合实现方式,因为后者拥有更好的性能和更好的数据封装特性。


4.栈Stack

简要概述:栈是Vector的一个子类,它实现了一个标准的后进先出的栈。

堆栈只定义了默认构造函数,用来创建一个空栈。 堆栈除了包括由Vector定义的所有方法,也定义了自己的一些方法。

Stack()

除了由Vector定义的所有方法,自己也定义了一些方法:

序号方法描述
1boolean empty() 测试堆栈是否为空。
2Object peek( ) 查看堆栈顶部的对象,但不从堆栈中移除它。
3Object pop( ) 移除堆栈顶部的对象,并作为此函数的值返回该对象。
4Object push(Object element) 把项压入堆栈顶部。
5int search(Object element) 返回对象在堆栈中的位置,以 1 为基数。

在Java中,栈(Stack)类被实现为一种后进先出(LIFO)数据结构。它基本上扩展了Vector类,使其可以实现添加、删除和查看从同一端进行数据处理的功能。

以下是Stack的几个基本方法:

  • push(E item):将元素压入栈中

  • pop():从栈中弹出顶部元素并返回该元素

  • peek():查看而不取出位于栈顶的元素

  • empty():当栈为空时返回true,否则返回false

  • search(Object o):在堆栈中搜索给定的元素并返回其相对位置,其中1表示达到顶部的第一个元素

以下是一个简单的栈的示例:

import java.util.*;
​
public class Example {
    public static void main(String[] args) {
        Stack<String> stack = new Stack<>();
​
        //Pushing elements into the stack
        stack.push("Java");
        stack.push("Python");
        stack.push("C++");
​
        //Peeking at the top value
        System.out.println(stack.peek());
​
        //Popping elements from the stack
        while(!stack.empty()) {
            System.out.println(stack.pop());
        }
    }
}

输出结果如下:

C++
C++
Python
Java

在这个示例中,我们定义了一个String类型的Stack,并使用push()方法向其中添加三个字符串。接着,我们调用peek()方法来获取最上面的元素(即“C++”),然后使用pop()方法将所有元素逐个从堆栈中移除并打印它们。由于栈是后进先出的,所以最后一个加入到堆栈中的元素会被首先弹出。

需要注意的是,Java Stack类已被认为是过时的API(自JDK 1.5起),因为它使用了Vector类,而Java的集合框架提供了更现代化和灵活的替代方案,例如LinkedList和ArrayDeque等。所以在实际编程中,建议使用这些新的类来代替Stack。


5.字典Dictionary

简要概述:字典(Dictionary) 类是一个抽象类,它定义了键映射到值的数据结构。

当你想要通过特定的键而不是整数索引来访问数据的时候,这时候应该使用Dictionary。

由于Dictionary类是抽象类,所以它只提供了键映射到值的数据结构,而没有提供特定的实现。

在Java中,字典(Dictionary)类表示一个关联数组,其中每个键都对应一个值。它是一个抽象类,不能被实例化,但可以通过其子类Hashtable和Properties创建实例。


6.哈希表HashTable

简要概述:Hashtable类提供了一种在用户定义键结构的基础上来组织数据的手段。

例如,在地址列表的哈希表中,你可以根据邮政编码作为键来存储和排序数据,而不是通过人名。

哈希表键的具体含义完全取决于哈希表的使用情景和它包含的数据。

Hashtable是Dictionary的具体子类之一,它实现了一个哈希表,数据以(key, value)的方式存储。每个非null key都映射到一个唯一的value,而不同key可以指向相同的value。

以下是Hashtable的几个基本方法:

  • put(Object key, Object value):将指定的key-value映射添加到Map中

  • get(Object key):返回与指定键关联的值

  • remove(Object key):从Map中删除指定的key及其对应的value

  • containsKey(Object key):如果Map中具有指定的key,则返回true

  • isEmpty():如果Map中不包含任何元素,则返回true

以下是一个简单的Hashtable示例:

import java.util.*;
​
public class Example {
    public static void main(String[] args) {
        // 创建一个Hashtable
        Hashtable<String, Integer> ht = new Hashtable<>();
​
        // 添加 key-value pairs(键值对) 到 Hashtable
        ht.put("John", 25);
        ht.put("Mary", 30);
        ht.put("Peter", 35);
​
        // 打印Hashtable
        System.out.println(ht);
        
        // 从 Hashtable中移除Mary这个key
        ht.remove("Mary");
        
        // 检查 peter key 是否存在于 Hashtable中
        System.out.println(ht.containsKey("Peter"));
        
        // 打印 Hashtable 的元素长度
        System.out.println(ht.size());
    }
}

输出结果如下:

{Peter=35, Mary=30, John=25}
true
2

在这个示例中,我们定义了一个Hashtable类,它将字符串作为键(key)和整数作为值(value)。使用put()方法向其中添加三个键值对,并打印Hashtable的内容。接着,我们使用remove()方法删除一个键及其值,并通过containsKey()方法检查另一个键是否存在于Hashtable中,最后使用size()方法打印Hashtable中元素的数量。

需要注意的是,在 Java 8 及以上版本中,Hashtable 已被认为是过时的API,建议使用HashMap 或 ConcurrentHashMap 来代替。


7.属性(Properties)

Properties 继承于 Hashtable.Properties 类表示了一个持久的属性集.属性列表中每个键及其对应值都是一个字符串。

Properties 类被许多Java类使用。例如,在获取环境变量时它就作为System.getProperties()方法的返回值。在Java中,属性(Properties)是一种特殊类型的Hashtable,它用于保存键值对,其中键和值都必须是字符串类型。通常,属性文件被用来保存应用程序的配置参数或者用于国际化。

以下是Properties的几个基本方法:

  • load(InputStream inStream):从输入流中读取属性列表(键和元素对)。

  • getProperty(String key):用指定的键在此属性列表中搜索属性。

  • setProperty(String key, String value):保存一个属性到属性列表中。

  • stringPropertyNames():返回一个包含当前所有属性键的Set<String>集合。

  • store(OutputStream out, String comments):将此属性列表(键和元素对)写入此 Properties表中。

以下是一个简单的Properties示例:

import java.util.*;
import java.io.*;
​
public class Example {
    public static void main(String[] args) throws IOException{
        // 创建一个Properties对象
        Properties prop = new Properties();
​
        // 添加一些属性
        prop.setProperty("name", "John");
        prop.setProperty("age", "25");
        prop.setProperty("gender", "Male");
​
        // 保存属性到文件中
        OutputStream output = new FileOutputStream("config.properties");
        prop.store(output, "我的配置");
        output.close();
​
        // 从文件中加载属性
        InputStream input = new FileInputStream("config.properties");
        prop.load(input);
        input.close();
​
        // 获取属性值
        System.out.println(prop.getProperty("name"));
​
        // 列出所有属性名和对应的值
        Set<String> keys = prop.stringPropertyNames();
        for(String key: keys){
            System.out.println(key + ": " + prop.getProperty(key));
        }
    }
}

在这个示例中,我们创建了一个Properties对象并添加了三个属 性。接着,我们使用store()方法将这些属性保存到名为“config.properties”的文件中,并在输出中显示了存储的注释。

然后,我们使用load()方法从配置文件中加载属性,并检索了其中一个属性的值。最后,我们列出了所有属性名称和对应的值。

需要注意的是,在Java 9及以上版本中,我们会使用更现代的偏向动态和模块化机制的库来管理属性文件,例如Java.util.prefs包或外部的配置库(如Apache Commons Configuration)等。

时间:2023/05/06-21:49分 以上仅为个人对Java高级编程的学习记录,有错误欢迎各位指出,交流学习!感谢观看

PS:我有自己学习笔记的md文件,有需要的可以评论获取,或者私聊我获取!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Stevedash

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值