一 、集合的定义
集合是由任意类型互不相同的数据元素组成的,它们之间没有任何逻辑关系。每一个元素都是相对独立的。在Java中,Object类是所有对象的根类,可以代表集合中任意一种数据类型。在Java中,Set接口来表示集合。集合分为顺序存储结构和链式存储结构,顺序结构是由数组来实现的,本博客讲述顺序存储结构相关代码的实现。
二、集合的抽象数据类型
抽象数据类型(ADT)包括数据和操作两个部分,数据也为一个集合,采用任意方式存储,操作指的就是方法。抽象数据类型定义如下:
ADT Set is
Data :
采用顺序结构存储
Operation:
initSet(); //创建一个集合并初始化为空集
add(obj); //想集合中插入一个元素
remove(obj); //从集合中删除指定的元素
contains(obj); //判断一个给定元素是否包含集合
value(i); //返回集合中第i个元素的值
find(obj); //从集合中按值查找并返回
size(); //求出元素中集合的个数
isEmpty(); //判断集合是否为空
output(); //输出集合中所有的元素
union(set); //求当前集合与参数集合set的并集并返回
intersection(set); //求当前集合与参数集合set的交集并返回
clear(); //清楚集合中的所有元素,使之变为空集
end Set
三 、操作的具体实现
1. 定义一个类SequenceSet,初始化集合为空
public class SequenceSet {
private int maxSize = 10; //定义数组的初始长度为10
private Object[] setArray; //定义存储集合的数组
private int length; //定义数组中所保存集合元素的个数
public SequenceSet(){ //无参构函数
length = 0; //集合初始为空,长度为0
setArray = new Object[maxSize]; //定义长度为maxSize的数组
}
public SequenceSet(int n){ //带初始长度的构造函数的定义
if(n<=0){
System.out.println("数组的长度要大于0,已退出运行!");
System.exit(1);
}
length = 0; //集合初始为空,长度为0
setArray = new Object[n]; //定义长度为n的数组
}
}
2. 向集合中插入一个元素
- 顺序查找集合中是否存在值为待插入值为obj的元素,若存在则不能插入,返回false,因为集合中不能存在相同的元素。
- 检查数组长度是否够用,若不够用则创建一个新的数组,然后把原来的数组复制到新数组中,最后把新数组赋值给原来的数组。
- 把obj的值插入到保存集合的后面的一个空位置上。
- 集合的长度加1。
- 插入成功返回true。
public boolean add(Object obj){
//判断元素是否存在,若存在则返回false
for (int i = 0; i < length; i++) {
if(setArray[i].equals(obj)) return false;
}
//如果数组的长度已经分配完,需要在创建一个新的数组,并且把setArray的内容复制到新数组中,然后进行赋值。
if(setArray.length == length){
Object[] temp = new Object[length*2+1];
System.arraycopy(setArray, 0, temp, 0, length);
setArray = temp;
}
//增加元素,长度加1
setArray[length] = obj;
length++;
return true;
}
3.从集合中删除一个元素
- 首先遍历数组,查找等于给定obj的元素
- 若存在则删除,把空出的位置让最后一个元素填充,length减1,返回true。
- 若不存在,则返回false,原集合的元素不变
public boolean remove(Object obj){
for (int i = 0; i < length; i++) { //遍历数组
if(setArray[i] == obj){ //如果存在相等元素,则将最后一个元素赋给删除的元素,长度减1
setArray[i] = setArray[length-1];
length--;
return true;
}
}
return false;
}
4.判断一个元素是否属于该集合
public boolean contains(Object obj){
//遍历数组,如存在相等的元素则返回true
for (int i = 0; i < length; i++) {
if(setArray[i].equals(obj)) return true;
}
return false;
}
5.返回集合中第i个元素
public Object value(int i){
if(i<=0||i>length){
System.out.println("i应该在1和length之间!");
System.exit(1);
}
return setArray[i-1]; //返回第i个位置,对应下标为i-1
}
6.从集合中按值查找元素
public Object find(Object obj){
//若集合中存在该元素,则返回obj,否则返回null
for (int i = 0; i < length; i++) {
if(setArray[i].equals(obj)) return obj;
}
return null;
}
7.返回集合的长度
public int size(){
return length;
}
8.判断集合是否为空
public boolean isEmpty(){
return length==0; //只需判断长度是否为0即可
}
9.输出集合中所有的元素
public void output(){
for (int i = 0; i < length; i++) {
System.out.println(setArray[i].toString());
}
System.out.println();
}
10.求两个集合的并集
public SequenceSet union(SequenceSet set){
//遍历当前集合中所有的元素
for (int i = 0; i < length; i++) {
//向set集合中添加当前元素
set.add(setArray[i]);
}
//返回并集集合,即set集合
return set;
}
11.求两个集合的交集
public SequenceSet intersection(SequenceSet set){
//求两个集合的最小长度
int minLength;
if(length<set.length){
minLength = length;
}else{
minLength = set.length;
}
//创建一个SequenceSet对象,用作存放两个集合的交集
SequenceSet tempSet = new SequenceSet(minLength);
//遍历当前集合中的每一个元素
for (int i = 0; i < length; i++) {
Object x= setArray[i];
//判断set集合是否包含该元素
boolean b =set.contains(x);
//如果包含当前集合中的该元素,则存入tempSet中,然后长度加1
if(b){
tempSet.setArray[tempSet.length++] = x;
}
}
return tempSet;
}
12.清空集合中的元素
public void clear(){
length = 0;
}
三、总结
看完这篇文章大家对顺序结构应该有了清楚的认识了,顺序结构的底层实现是数组,然而数组的长度是不可变的,所有出现了扩容的情况,下次我们将讲述集合的另一种实现方式–链表。上面的代码大家应该手动敲一遍,你会有很大收获。学无止境,加油吧,少年!