Java基础数据结构

109 阅读7分钟

一、数据结构

栈、队列、数组、链表和红黑树:

1.1 常见数据结构

1.1.1 栈

先进后出

入/压栈:元素进入栈底往上排

出/弹栈:元素从栈顶依次取出

1.1.2 队列

先进先出

1.1.3 数组

查找快,增删慢

查找快: 数组地址是连续的,通过数组的首地址可以找到数组,通过索引可以找到元素;

增删慢: ,增加/删除一个元素,必须创建新数组,把新数组的内容复制过来;

1.1.4 链表

查询慢,增删快

查询慢: 链表种的地址不是连续的,每次查询都必须从头开始查询;

增删快: 链表结构增加删除,对链表整体结构没有影响

一个节点包括【自己的地址+存储数据+下一个节点的地址

单向链表: 链表种只有一条链子,不能保证元素的顺序(存储元素和取出元素的顺序有可能不一样)

双向链表: 链表种又两条链子,一条专门记录元素的顺序,是一个有序的集合;

1.1.5 红黑树

二叉树: 分支不能超过两个;

排序树/查找树: 在二叉树的基础上,元素是有大小顺序的;

左子树小,右子树大

image.png 平衡树: 左孩子和右孩子数量相等

不平衡树: 左孩子!=右孩子

红黑树:

特点:趋近于平衡树,查询的速度非常的快,查询叶子节点最大次数和最小次数不能超过2倍;

约束: 1、节点可以是红色或者黑色的;

2、根节点是黑色的;

3、叶子节点(空节点)是黑色的;

4、每个红色的节点的子节点都是黑色的;

5、任何一个节点到其每一个叶子节点的所有路径上的黑色节点数是相同的

二、List 集合

三大特点: 有序的Collection集合,有索引;允许存储重复的元素;

List中带索引的方法:add,get,remove,set;

注意:操作索引时,防止索引越界异常;

2.1 常用方法

void add( int index , E element )

E remove( int index)

E set( int index ,E element)

E get( int index )

2.2 List 有三种遍历方法:

1、普通for循环,get方法

2、迭代器遍历

Iterator it=List.iterator();

while(it.hasNext()){

String s=it.next();

sout s;

}

3、增强FOR循环

快捷键:list.for

for(String s:List){

Sout s

}

三、List中的子类

3.1 ArrayList 集合

List 接口的大小可变数组的实现,不是同步的【多线程】

查询快,增删慢

3.2 LinkedList 集合

List 接口的链接列表实现,不是同步的【多线程】

双向链表:首位元素的操作多

特点: 1、底层是链表结构:查询慢,增删快;

2、包含大量操作首尾元素的方法;

注意:使用LinkedList集合特有的方法,不能使用多态;

addFirst(E e);

addLast(E e); 等效于add(E e)

push(E e); 将元素推入此列表的堆栈;等效于addFirst;

E getFirst();

E getLast();

E removeFirst();

E removeLast();

E pop(); 从此列表的对战处弹出一个元素;等效于removeFirst

boolean isEmpty()

3.3 Vector

可以实现可增长的对象数组,【同步的】

四、Set接口

特点: 1、不包含重复元素的collection

2、没有索引,没有带索引的方法,也不能使用普通for循环的遍历;

4.1 HashSet 集合

特点: 哈希表结构,(查询速度非常快)

无序集合,存储元素喝取出元素的顺序可能不一致;

4.1.1 哈希值

哈希值: 是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来得到地址,不是数据实际存储的物理地址;)

Object类中有一个方法可以获取对象的哈希值;

【int hashCode();】返回该对象的哈希数值

native:代表该方法调用的是本地操作系统的方法;

String类的哈希值,重写了Object的hashCode;

4.1.2 哈希表

JDK1.8之前,哈希表=数组+链表

JDK1.8之后,哈希表=数组+链表

哈希表=数组+红黑树(提高查询效率)

哈希表的特点:速度快

两个元素不同,hash值相同【哈希冲突

数据结构: 把元素进行了分组(相同的哈希值的元素是一组)链表/红黑树结构把相同哈希值的元素链接到一起;

如果链表的长度超过8位,那么就会把链表转换成红黑树(加快查询速度)

set集合保证元素唯一:必须重写hashCode方法和equals方法; 【没有重写之前比较的都是地址值】

4.2 HashSet 存储自定义类型元素

必须重写hashCode和equals方法;

4.2.1 LinkedHashSet 集合

可预知的迭代顺序;

底层是一个哈希表,多了一条链表(记录元素的存储顺序),保证元素有序;

【有序,且不允许重复】

4.3 可变参数

使用前提:当方法的参数列表数据类型已经确定,但是参数的个数不确定,就可以用可变参数

修饰符 返回值类型 方法名 (数据类型... 变量名){}

可变参数的底层是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些参数

传递的参数可以是0,1,2,3,...个

可变参数的注意事项:1、一个方法的参数列表,只能有一个可变参数

2、如果方法的参数有多个,那么可变参数必须写在参数列表的末尾

可变参数的终极写法:method(Object...obj)

public class Various {
  public static void main(String[] args) {
      //int a=add(10,20);
      int a=add(10,20,30);
      System.out.println(a);
  }
  //定义计算(0-n个)整数的和
  public static int add(int...arr){
      System.out.println(arr); //[I@1540e19d 底层是一个数组
      System.out.println(arr.length);     //传递参数的个数
      //定义一个初始化的变量,记录累加求和
      int sum=0;
      //遍历数组,获取数组中的每一个元素
      for (int i : arr) {
          //累加求和
          sum+=i;
      }
      return sum;
  }
}

五、Collections

5.1 常用功能

集合工具类

方法:

image.png

image.png image-20200921110420611

image.png 注意事项:sort()使用前提:

被排序的集合里面存储的元素,必须实现Comparable,重写接口方法中的compareTo方法

Comparable接口的排序规则:

自己(this) — 参数 【升序】

【charAt(0)方法可以拿来提取char元素的第1...个元素】

public class DemoColl {
  public static void main(String[] args) {
      ArrayList<String> list=new ArrayList<>();
      Collections.addAll(list,"a","b","c"); //一下子添加多个
      System.out.println(list);
      Collections.shuffle(list);     //打乱元素顺序
      System.out.println(list);
  }
}
public class Person implements Comparable<Person> {
  private String name;
  private int age;
​
  public Person() {
  }
​
  public Person(String name, int age) {
      this.name = name;
      this.age = age;
  }
​
  @Override
  public String toString() {
      return "Person{" +
              "name='" + name + ''' +
              ", age=" + age +
              '}';
  }
​
  public String getName() {
      return name;
  }
​
  public void setName(String name) {
      this.name = name;
  }
​
  public int getAge() {
      return age;
  }
​
  public void setAge(int age) {
      this.age = age;
  }
​
  @Override
  public int compareTo(Person o) {
      //return 0; //认为元素都是相同的
      //自定义比较规则,比较年龄
      return this.getAge()-o.getAge();//年龄升序排序
  }
}
public static void main(String[] args) {
  ArrayList<Integer> list=new ArrayList<>();
  list.add(1);
  list.add(4);
  list.add(3);
  list.add(2);
  System.out.println(list);   //[1, 4, 3, 2]
​
  Collections.sort(list);
  System.out.println(list); //sort排序后默认升序 [1, 2, 3, 4]
​
  ArrayList<String> list2=new ArrayList<>();
  Collections.addAll(list2,"a","c","b","d");
  Collections.sort(list2);
  System.out.println(list2); //排序后 [a, b, c, d]
​
  ArrayList<Person> ps=new ArrayList<>();
  ps.add(new Person("张三",20));
  ps.add(new Person("李四",21));
  ps.add(new Person("王五",19));
  System.out.println(ps);   //[Person{name='张三', age=20}, Person{name='李四', age=21}, Person{name='王五', age=19}]
​
  Collections.sort(ps);
  System.out.println(ps);
}

Comparator和Comparable的区别:

Comparable:自己(this)和别人(参数)做比较,自己需要实现Comparable接口,重写比较的规则CompareTo;

Comparator:相当于找一个第三方裁判来比较

//sort(list, new Comparator)方法的使用public class DemoComparator {
  public static void main(String[] args) {
      ArrayList<Integer> list=new ArrayList<>();
      Collections.addAll(list,1,3,6,2);
      Collections.sort(list, new Comparator<Integer>() {
          //重写比较的规则
          @Override
          public int compare(Integer o1, Integer o2) {
              return o1-o2;//升序
              //return o2-o1; //降序
          }
      });
      System.out.println(list);
  }
}

六、Map

  • public interface **Map<K,V>**

将键映射到值的对象。一个映射不能包含重复的键每个键最多只能映射到一个值

Map集合的特点:

1、Map集合是一个双列集合,一个元素包含两个值(一个key,一个value);

2、Map集合中的元素,key和value的数据类型可以相同也可以不同;

3、Map集合中的元素,key是不允许重复的,value是可以重复的;

4、Map集合中的元素,key和value是一一对应的;

image.png

6.1 常用子类HashMap和LinkedHashMap

HashMap<k,v>实现了Map<k,v>接口,

HashMap的特点:

1、底层是哈希表,查询速度非常快;

2、是一个无序的集合,存储元素和取出元素的顺序可能不一致;【LinkedHashMap<k,v>继承了HashMap,实现了有序】

LinkedHashMap的特点:

1、底层是哈希表+链表

2、是一个有序的集合,存储元素和取出元素的顺序是一致的;

6.2 Map接口中的常用方法

V put(K key,V value) 将指定的值与此映射中的指定键关联

V get(Object key) 返回指定键所映射的值

V remove(Object key) 如果存在一个键的映射关系,则将其从此映射中移除

boolean containKey(Object key) 确定是否存在映射关系

注意事项:

put方法的返回值:1、Key如果不重复,返回值为null;

2、key重复,会使用新的value替换map中的重复的value,返回被替换掉的value值;