學習了一段時間的Java,我們對Java的基本知識有了一定的瞭解,今天再來聊聊數組。
Java內置數組的特點
-
數組的長度一旦確定則不可更改
-
數組只能存儲同一類型的數據
-
數組中每個存儲空間大小一致且地址連續
-
數組提供角標的方式訪問元素
我們發現數組又有一些侷限性,於是在使用時又會有一些疑惑,我們可以總結一下
Java內置數組的潛在問題
容量不夠用時,怎麼辦?
指定位置插入或刪除元素,怎麼做?
數組對象只有length屬性,能滿足更多的需求嗎?
動態數組的封裝
有了問題,我們就有想法,嘗試用學過的知識來解決
能否用面向對象的思想,將數組進行再度封裝呢?
可以的,我們可以把數組的相關屬性和相關行爲封裝在類中
類似字符串String類,形成如下的調用形式
String s="HelloWorld";
s.charAt(1);
s.compareTo("Hello");
s.equals("Hello");
s.repalce('l','L');
數組對象.排序()
數組對象.插入(元素)
數組對象.查找(角標)
這樣大大方便了我們對數組的操作
那麼如何封裝動態數組
屬性方面:
- int size 數組的有效元素個數
- int capacity 數組的最大容量data.length
- E[] data 數據的存儲容器
行爲方面:
- 增()
- 刪()
- 改()
- 查()
- 其他()
爲什麼要強調動態數組
動態數組是順序存儲結構的具體實現!
1)線性表的定義
零個或多個數據元素的有限序列
2)線性表接口List的定義
定義線性表的接口List
List支持泛型E
該List線性表中所存儲的具體數據類型由外界決定
public interface List<E> extends Iterable<E>{
//獲取線性表中元素的有效個數
int getSize();
//判斷線性表是否爲空表
boolean isEmpty();
//在線性表指定的index角標處插入元素e
void add(int index,E e);
//在線性表的表頭處插入元素e
void addFirst(E e);
//在線性表的表位處插入元素e
void addLast(E e);
//獲取線性表中指定角標index處的元素
E get(int index);
//獲取表頭元素
E getFirst();
//獲取表尾元素
E getLast();
//修改線性表中指定角標index處的元素爲新元素e
void set(int index,E e);
//判斷線性表中是否包含元素e
boolean contains(E e);
//查找元素e的角標(從左到又默認第一個出現的元素角標)
int find(E e);
//刪除並返回線性表中指定角標index處的元素
E remove(int index);
//刪除並返回表頭元素
E removeFirst();
//刪除並返回表尾元素
E removeLast();
//刪除指定元素e
void removeElement(E e);
//清空線性表
void clear();
}
創建線性表List的順序存儲結構實現類ArrayList
public class ArrayList<E> implements List<E>{
//創建E類型的一維數組
private E[] data;
//維護元素個數
private int size;
//默認最大容量爲10
private static int DEFAULT_CAPACITY=10;
}
先創建一個順序表 ,重寫函數來獲取元素有效個數與判斷是否爲空
//創建一個默認大小的順序表
public ArrayList(){
this(DEFAULT_CAPACITY);
//data=(E[])(new Object[DEFAULT_CAPACITY]);
}
//創建一個容量由用戶指定的順序表
public ArrayList(int capacity){
if(capacity<=0) {
throw new IllegalArgumentException("容量>0:" + capacity);
}
data=(E[])(new Object[capacity]);
size=0;
}
//用戶傳入一個數組 將該數組封裝成一個順序表
public ArrayList(E[] data){
if(data==null){
throw new IllegalArgumentException("數組不能爲空");
}
this.data=(E[])(new Object[data.length]);
for (int i = 0; i <data.length ; i++) {
this.data[i]=data[i];
}
size=data.length;
}
@Override
public int getSize() {
return size;
}
@Override
public boolean isEmpty() {
return size==0;
}
在指定角標插入元素時,如果數組已滿,則需要擴容
@Override
public void add(int index, E e) {
if(index<0||index>size){
throw new IllegalArgumentException("角標越界");
}
if(size==data.length){
//擴容
resize(data.length*2);
}
for (int i = size; i >index ; i--) {
data[i]=data[i-1];
}
data[index]=e;
size++;
}
private void resize(int newLength) {
E[] newData=(E[])(new Object[newLength]);
for (int i = 0; i < size; i++) {
newData[i]=data[i];
}
data=newData;
}
@Override
public void addFirst(E e) {
add(0,e);
}
@Override
public void addLast(E e) {
add(size,e);
}
獲取指定元素位置
@Override
public E get(int index) {
if(isEmpty()){
throw new IllegalArgumentException("線性表爲空");
}
if(index<0||index>=size){
throw new IllegalArgumentException("角標越界");
}
return data[index];
}
@Override
public E getFirst() {
return get(0);
}
@Override
public E getLast() {
return get(size-1);
}
修改線性表中指定角標index處的元素爲新元素e
@Override
public void set(int index, E e) {
if(isEmpty()){
throw new IllegalArgumentException("線性表爲空");
}
if(index<0||index>=size){
throw new IllegalArgumentException("角標越界");
}
data[index]=e;
}
查找元素e的角標(從左到又默認第一個出現的元素角標)
@Override
public boolean contains(E e) {
return find(e)!=-1;
}
在數組中查找是否含有指定元素e
@Override
public int find(E e) {
if(isEmpty()){
throw new IllegalArgumentException("線性表爲空");
}
for (int i = 0; i < size; i++) {
if(data[i].equals(e)){
return i;
}
}
return -1;
}
刪除並返回線性表中指定角標index處的元素
@Override
public E remove(int index) {
if(isEmpty()){
throw new IllegalArgumentException("線性表爲空");
}
if(index<0||index>=size){
throw new IllegalArgumentException("角標越界");
}
E ret=data[index];
for(int i=index+1;i<size;i++){
data[i-1]=data[i];
}
size--;
if(size<=data.length/4&&data.length/2>=10){
resize(data.length/2);
}
return ret;
}
@Override
public E removeFirst() {
return remove(0);
}
@Override
public E removeLast() {
return remove(size-1);
}
刪除指定元素e
@Override
public void removeElement(E e) {
int index=find(e);
if(index!=-1){
remove(index);
}else{
throw new IllegalArgumentException("元素不存在");
}
}
清空線性表
@Override
public void clear() {
size=0;
data=(E[])(new Object[DEFAULT_CAPACITY]);
}