线性表基本概念
线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储
- > 线性表不允许中间有空洞
注意: 顺序表中一定要区分两个概念 容量(capacity) vs 元素个数(size);线性表的所有下标只和元素个数相关,和容量无关 .
顺序表基本概念
顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元,依次存储线性表中的各个元素、使得线性表中再逻辑结构上响铃的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系。
数组中存在的问题:
1.无法严格区分容量和已有元素的个数
2.数组无法做到自行扩容
java中已经提供的顺序表—java.util.ArrayList
ArrayList是一个泛型类,元素类型使用泛型表示
ArrayList重要方法
public boolean add(E e);向顺序表中进行尾插,一定
会返回true。注意:放在目前最后一个元素的后边,而不是
容量的最后一个位置。
public void add(int index,E element);向顺序表
中插入e元素,放到下标为index的位置,注意index的合
法下标是0~size
如:顺序表 [a,b,c]现在调用方法add(1,元素),此时会将b,c依次向后移,将要插入的元素放在1下标。
举个栗子:
ArrayList<String> list = new ArrayList<>();
list.add("1");
list.add(2,"1");
System.out.println(list.size());
报错:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 2, Size: 1
上面这个代码会报错,因为此时的size是1,下标2超出了范围,所以越界报错了。
改为以下代码就不会报错了,因为插入index的合法范围是0~size
ArrayList<String> list = new ArrayList<>();
list.add("1");
list.add(1,"2");
System.out.println(list.size());
问:index的取值范围是什么?和容量有关还是和size有关?
回答:和size有关,和容量无关。
public E remove(int index);删除index位置的元素,返回
被删除的元素;删除的时候合法的下标取值范围是[0,size-1]。
删掉一个元素后该元素后面的元素会依次向前移动一位,顺序
表的元素个数减一。
public boolean remove(Object o);删除指定元素
1.如果该元素在顺序表中并且只有一个,则删除该元素,并且将
后面的元素依次补上,返回true
2.如果该元素没有在顺序表中,什么都不做,返回false,表示
该元素不在顺序表中
3.如果在元素在顺序表中存在且不止一个,则删除第一个遇到
的元素,并且返回true。
public E get(int index);获取顺序表中index位置的元素
并且返回该元素
public E set(int index,E element);向顺序表中index
位置设置元素进去,并且返回该下边位置原来的元素
下标的取值范围都是[0,size)
栗子:
[a,b,c]
get(1) 得到b
set(1,"d") 将1下标设置为d并且返回b
public boolean contains(Object o);
判断顺序表中是否包含该元素,包含返回true,不包含返回
false;
public int indexOf(Object o);返回此列表中第一次
出现的指定元素的索引,如果列表不包含该元素,则返回 -1;
返回该元素怒从前往后找的首次遇到的下标,如果没找到就
返回-1
public int lastIndexOf(Object o);返回列表中最后出现
的指定元素的索引;如果列表不包含此元素,则返回 -1 返回
该元素怒从后往前找的首次遇到的下标,如果没找到就返回-1
public void clear();清空一个顺序表,无论原来顺序表
中有没有元素,调用改方法后,size==0
public int size();返回顺序表中当前已有的元素个数
public boolean isEmpty();等价于size == 0,如果此列表
中没有元素,则返回 true
Iterable中的方法
public interface Iterable<T> {
Iterator<T> iterator();//通过iterator()方法返回迭代器,通过迭代器可以进一步的进行迭代
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
使用栗子:
import java.util.ArrayList;
import java.util.Iterator;
public class ArrayListDemo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("1");
list.add(1,"2");
list.add("3");
Iterable<String> r1 = list; //r1指向的对象具备迭代能力
//1.通过r1得到迭代器对象
Iterator<String> iterator = r1.iterator();
// System.out.println(iterator.hasNext());
// String s1 = iterator.next(); //返回“1”,iterator内部走到了“2”
//
// System.out.println(s1);
// System.out.println(iterator.hasNext());
// String s2 = iterator.next();
// System.out.println(s2);
//
// System.out.println(iterator.hasNext());
// String s3 = iterator.next();
//
// System.out.println(s3);
// System.out.println(iterator.hasNext());
//不知道元素个数进行迭代
while (iterator.hasNext()){
String s = iterator.next();
System.out.println(s);
}
}
}
Iterator类似于之前学过的Scanner
public interface Iterator<E> {
boolean hasNext(); //返回true:还有下一个/没有迭代完,返回false:没有下一个了/迭代完了
E next(); //1.返回下一个元素 2.同时跳过该元素(这个元素被迭代过了),基于hasNext()返回true的前提
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
Collection中的方法
public interface Collection<E> extends Iterable<E> {
boolean add(E e);//Collection代表的不一定是线性表,所以没有次序的概念,add可以返回false也可以返回true,但List一定返回true
void clear();//清空集合
int size(); //返回集合中元素的个数
boolean isEmpty();//判断是否是一个没有元素的集合
boolean contains(Object o);//判断是否存在,和equals方法相关
boolean remove(Object o);//从集合中删除o元素
Iterator<E> iterator();
}
Collection接口的栗子:
public class CollectionDemo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
Collection<String> collection = list;
System.out.println(collection);
for (String s : collection){
System.out.println(s);
}
collection.remove("1");
System.out.println(collection.isEmpty());
System.out.println(collection.add("4"));
collection.clear();
System.out.println(collection.isEmpty());
}
}
通过引用可以执行哪些方法------引用类型决定
通过引用执行方法后真正执行的是哪个类的方法-----引用指向的对象类型决定
只有线性表才有是否有序这个概念。
List接口中的方法
public interface List<E> extends Collection<E> {
void sort(Comparator 比较器);
List subList(int fromIndex, int toIndex); //包含fromIndex不包含toIndex
boolean addAll(Collection 集合);
boolean addAll(int index, Collection 集合);
boolean containsAll(Collection 集合);
boolean removeAll(Collection 集合);
boolean retainAll(Collection 集合);
Object[] toArray();
}
排序栗子:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ListSortDemo {
private static class IntegerComparator implements Comparator<Integer>{
@Override
public int compare(Integer o1, Integer o2) {
return o1.intValue() - o2.intValue();
}
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(4);
list.add(2);
list.add(7);
//方法1
System.out.println(list);
list.sort(new IntegerComparator());
System.out.println(list);
//方法2
//Collections里面放的是给集合对象用的常见方法
Collections.sort(list);
System.out.println(list);
//方法3
Collections.sort(list,new IntegerComparator());
System.out.println(list);
//如果要实现逆序排序,可以修改实现方法compareTo,然后使用上面的方法1和3就能达到逆序排序
}
}
}
总结
方法:
增(向容器中添加元素)add
删(从容器中删除元素)remove
查(不修改容器的情况下,获取元素get/contains/indexOf/lastIndexOf
改(修改个别元素)set
还有size/isEmpty核心:
顺序表中不允许出现空洞 index的下标的合法取值,肯定和size()有关
add:[0,size]
remove/get/set:[0,size)