文章目录

  • 第一章 数据结构
  • 常见的数据结构
  • 队列
  • 数组
  • 链表
  • 红黑树
  • 第二章 List集合
  • 2.1 List接口介绍
  • 2.2 List中的常用方法
  • 第三章 List的子类
  • 3.1 ArrayList集合
  • 3.2 LinkedList集合
  • 第四章 Set接口
  • 4.1 HashSet集合介绍
  • 4.2 HashSet集合存储数据的结构(哈希表)
  • Set集合不允许存重复元素的原理
  • 4.3 HashSet储存自定义类型元素
  • 4.4 LinkedHashSet
  • 4.5 可变参数
  • 第五章 collections
  • 5.1 常用功能

第一章 数据结构

常见的数据结构

  • stack又称为栈,他是运算受限的线性表,其限制是仅允许在标的一端进行插入和删除的操作,不允许在其他任何位置进行添加、查找、删除等操作。

特点

  • 先进后出
  • 栈的入口、出口都是栈的顶端位置

队列

  • queue,他和栈一样,都是一种受限的线性表,其限制是仅允许在表的一端进行插入,另一端进行删除

特点

  • 先进先出
  • 队尾入队、队头出队

数组

懒得看了

链表

懒得看了

红黑树

java list把元素放在第一位 java list指定位置_List

第二章 List集合

Colltion接口中的两个常用子类java.util.Listjava.util.Set

2.1 List接口介绍

该接口是单列集合的一个重要分支,习惯性地会实现了List接口的对象称为List集合.在LIst集合中允许出现重复的元素,所有的元素以一种线性的方式存储的,他有序(存入顺序和去除顺序一致)

List接口特点

  1. 他是一个元素存取的有序集合.
  2. 他是一个带有索引的集合,
  3. 集合中还可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素,

2.2 List中的常用方法

void add(int index, E element) 
          在列表的指定位置插入指定元素(可选操作)。 
          
  void clear() 
          从列表中移除所有元素(可选操作)。 
          
          
E get(int index) 
          返回列表中指定位置的元素。 
          
          
          
int indexOf(Object o) 
          返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。   
          
          
 E remove(int index) 
          移除列表中指定位置的元素(可选操作)。 
          
          
 E set(int index, E element) 
          用指定元素替换列表中指定位置的元素(可选操作)。 
          
          
  int size() 
          返回列表中的元素数。 
          
          
   Object[] toArray() 
          返回按适当顺序包含列表中的所有元素的数组(从第一个元素到最后一个元素)。

第三章 List的子类

3.1 ArrayList集合

这个是线性表中的顺序表,元素增删和查找复杂度是n,但是查找快,如果经常需要遍历和查询数据,那么该类是很合适的

3.2 LinkedList集合

该类的数据结构是链表结构(双向链表).方便添加和删除(复杂度为1),但是查找就是慢(复杂度为n)

常用方法:

void add(int index, E element) 
          在此列表中指定的位置插入指定的元素 
    
 void addFirst(E e) 
          将指定元素插入此列表的开头。 
    
 void addLast(E e) 
          将指定元素添加到此列表的结尾。
    
 void clear() 
          从此列表中移除所有元素。 
    
  E get(int index) 
          返回此列表中指定位置处的元素。 
    
   E pop() 
          从此列表所表示的堆栈处弹出一个元素。 
    
  void push(E e) 
          将元素推入此列表所表示的堆栈。
    
  E remove() 
          获取并移除此列表的头(第一个元素)。
    
   E remove(int index) 
          移除此列表中指定位置处的元素。
    
     E removeFirst() 
          移除并返回此列表的第一个元素。 
    
     E removeLast() 
          移除并返回此列表的最后一个元素。 
    
    
   E set(int index, E element) 
          将此列表中指定位置的元素替换为指定的元素。 
    
 int size() 
          返回此列表的元素数。
    
 Object[] toArray() 
          返回以适当顺序(从第一个元素到最后一个元素)包含此列表中所有元素的数组。

示例:

package Practice;

//其里面包含了大量连接首尾的元素
import java.util.LinkedList;

public class Demo1 {
    public static void main(String[] args) {
        LinkedList<String> aaa = new LinkedList<>();
        //使用add方法来添加元素
        aaa.add("a");
        aaa.add("b");
        aaa.add("c");
        System.out.println(aaa);
        aaa.addFirst("www");
        System.out.println(aaa);
        aaa.push("aaaaa");
        System.out.println(aaa);
        aaa.pop();
        System.out.println(aaa);
    }
}

第四章 Set接口

该接口并没有对Collection接口进行功能上的拓展,只是比Collection接口更严格了.与LIst接口不同的是,Set接口中无序,并且都会以某种规则保证存入的元素不再重复.

set集合有多个子类,我们在这里介绍java.util.HashSet,java.util.LinkedHashSet这两个集合.

//注意: Set集合取出元素的方式也可以使用: 迭代器,增强for

特点:

  • 不允许有重复的元素
  • 没有索引,没有带索引的方法,也不能使用普通的for循环遍历
package demo03;


import java.util.HashSet;
import java.util.Set;

public class DoudiZhu {
    public static void main(String[] args) {
        Set<Integer> set = new HashSet<>();
        set.add(111);
        set.add(211);
        set.add(511);
        set.add(711);
        set.add(411);
        set.add(911);
        set.add(1011);
        set.add(111);
        for (Integer integer : set) {
            System.out.println(integer);//我们会发现取出的顺序和遍历的顺序不一致,且不允许存进同样的元素  
        }
    }
}

4.1 HashSet集合介绍

特点:

  1. 无序的集合**,没有带索引的方法**,储存元素和取出元素的顺序有可能不一致
  2. 此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。

HashSet是**根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存储和查找性能.**保证元素唯一性的凡是依赖于:hashCodeequals方法

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

  • Object类中有个int hashCode()方法可以获取Hash值
public native int hashCode();
  • native代表调用的是本地操作系统的方法

他的一些示范和现象

package demo03;


import java.util.ArrayList;

public class DoudiZhu extends Object {
    public static void main(String[] args) {


        ArrayList<String> arr = new ArrayList<>();
        ArrayList<String> arr1 = new ArrayList<>();

        arr1.add("我是你爹");

        System.out.println(arr.hashCode());//这个是1
        System.out.println(arr1.hashCode());//这个不是空数组了,所以分配了,这个类重写了hashCode方法

        GenericMethod aa = new GenericMethod();
        System.out.println(aa.hashCode());//1595428806


        //字符串类  重写了hashCode方法
        String s1 = new String("abc");
        String s2 = new String("abc");
        //我们会发现他们的值一样
        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());

        //我们会发现下面这两个也一样
        System.out.println("我是你爹".hashCode());
        System.out.println("我是你大".hashCode());

        //但是个数不一样的时候就不一样了
        System.out.println("我是你爹".hashCode());
        System.out.println("我是你大爷".hashCode());
    }
}

4.2 HashSet集合存储数据的结构(哈希表)

在JDK1.8之前,哈希表底层采用数组+链表实现,同同一hash值得链表都储存在一个链表里面。但是当位于一个桶中的元素较多,即hash值相等得元素较多时,通过key值一次查找得效率较低

所以1.8之后,哈希表采用数组+链表+红黑树实现

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

注意:

  • 两个元素要是内容不同,但是哈希值相同,那么就会引起哈希冲突,两个元素就会同时放在一个组中
  • 同一组中的数据要是小于8,那么用链表连接,要是大于8,那么就用红黑树连接(因为查询速度会很快)

java list把元素放在第一位 java list指定位置_java_02

Set集合不允许存重复元素的原理

  • add方法会调用元素的hashCode和equals方法来判断元素是否重复
  • 先调用hashCode方法来判断是否有相等哈希值的元素
  • 如果有的话,调用equals方法进行两个元素的比较
  • 1 如果元素相同的话,那么就不会存储
  • 2 如果元素不同的话,那么就会存储,这两个元素形成链表或者红黑树
  • 没有的话,就加入

注意:实现的前提是重写了hashCode方法和equals方法

代码测试:

package Practice;

//其里面包含了大量连接首尾的元素
import java.util.HashSet;
import java.util.LinkedList;

public class Demo1 {
    public static void main(String[] args) {
        HashSet<String> hash = new HashSet<>();
        String s1 = new String("abc");
        String s2 = new String("abc");

        hash.add(s1);
        hash.add(s2);
        hash.add(s2);
        hash.add(s2);
        hash.add(s2);
        hash.add("种地");
        hash.add("通话");

        System.out.println(hash);

    }
}
//运行结果
[通话, abc, 种地]

4.3 HashSet储存自定义类型元素

给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法

因为不重写的话,新创建的对象,他们的哈希值和地址值都是不一样的,所以说肯定可以存进集合里面

创建Student类

要求:同名同年龄的人,只能存储一次

//Student类
package Practice;

import java.util.Objects;

public class Student {
    private String name;
    private int age;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && name.equals(student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Student() {
    }

    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;
    }
}
//主函数
package Practice;


import java.util.HashSet;

public class Demo1 {
    public static void main(String[] args) {
        Student p1 = new Student("小美女",18);
        Student p2 = new Student("小美女",18);

        HashSet<Student> set = new HashSet<>();

        set.add(p1);
        set.add(p2);

        //在没有对HashCode方法和equals方法重写的时候,这两个还是可以一起存储
        //重写了之后就可以了
        System.out.println(set);


    }
}

4.4 LinkedHashSet

我们知道HashSet保证元素唯一,可以元素存进去是没有顺序的,那么我们要保证有序,要怎么办呢?你懂的

注意:这个类是 HashSet类的子类

  • 这个类维护着一个运行与所有条目的双重链接列表,它具有可预知的迭代顺序

也就是说,底层是 哈希表+链表的组合

这个链表用来存储元素的存储顺序

演示代码:

package Practice;

import java.util.LinkedHashSet;

public class Demo1 {
    public static void main(String[] args) {
        LinkedHashSet<Integer> set = new LinkedHashSet<>();

        set.add(1);
        set.add(2);
        set.add(3);
        set.add(4);
        set.add(5);
        set.add(6);
        
        //我们会发现,这里按顺序迭代出来了

        for (Integer integer : set) {
            System.out.println(integer);
        }
    }
}

4.5 可变参数

在JDK1.5之后,如果我们定义一个方法能接受读个参数,并且参数类型一致,我们就可以简化成如下形式:

修饰符  返回值类型  方法名(参数类型...形参名){   }

其实这个书写完全等价于

修饰符  返回值类型 方法名(参数类型[] 形参名){   }
  • 因为其底层就是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些参数,甚至可以不传递参数
package Practice;

//类型确定,但是个数不确定,就可以使用

public class Demo1 {
    public static void main(String[] args) {

        System.out.println(sum());
    }
    public static int sum(int...a){
        //a相当于就是一个数组
        int sum = 0;
        for (int i : a) {
            sum+=i;
        }
        return sum;
    }
}

注意事项

  • 一个方法的可变参数只能有一个
  • 可变参数必须写在参数的末尾

第五章 collections

5.1 常用功能

部分方法如下:

static <T> boolean addAll(Collection<? super T> c, T... elements) 
          将所有指定元素添加到指定 collection 中。 
    
    
static void shuffle(List<?> list) 
          使用默认随机源对指定列表进行置换。 
    
    
 static <T extends Comparable<? super T>> void sort(List<T> list) 
          根据元素的自然顺序 对指定列表按升序进行排序。 
    
    
static <T> void sort(List<T> list, Comparator<? super T> c) 
          根据指定比较器产生的顺序对指定列表进行排序。

示例代码:

package Practice;

//类型确定,但是个数不确定,就可以使用

import java.util.ArrayList;
import java.util.Collections;

public class Demo1 {
    public static void main(String[] args) {
        ArrayList<String> arr = new ArrayList<>();
        //添加方法
        Collections.addAll(arr,"你爹","你爷爷","你妈","你儿子");
        System.out.println(arr);//[你爹, 你爷爷, 你妈, 你儿子]


        //随机打乱
        Collections.shuffle(arr);//这个方法直接对源数组进行改变
        System.out.println(arr);//[你儿子, 你爷爷, 你爹, 你妈]

        //整理函数,默认按照升序规则排序,只能传list集合
        Collections.sort(arr);
        System.out.println(arr);//[你儿子, 你妈, 你爷爷, 你爹]
        
        Comparator<String> aaa = new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.charAt(0) - o2.charAt(0);
            }
        };

        //这个是自定义了规则的排序
        Collections.sort(arr,aaa);
        System.out.println(arr);

    }
}

注意

  • 数组里面要是放的是自定义的类,那么那个类一定要实现Comparable接口 你妈, 你儿子]
//随机打乱
  Collections.shuffle(arr);//这个方法直接对源数组进行改变
  System.out.println(arr);//[你儿子, 你爷爷, 你爹, 你妈]

  //整理函数,默认按照升序规则排序,只能传list集合
  Collections.sort(arr);
  System.out.println(arr);//[你儿子, 你妈, 你爷爷, 你爹]
  
  Comparator<String> aaa = new Comparator<String>() {
      @Override
      public int compare(String o1, String o2) {
          return o1.charAt(0) - o2.charAt(0);
      }
  };

  //这个是自定义了规则的排序
  Collections.sort(arr,aaa);
  System.out.println(arr);}
 }
**注意**

- 数组里面要是放的是自定义的类,那么那个类一定要**实现Comparable接口**
- 或者可以使用Compartor接口,相当于找一个第三方的裁判来找一下这个人