当前位置:   article > 正文

Java基础知识点集合(学习集合这一篇就够了)_java集合知识点

java集合知识点

集合是java中存储对象的容器,不能存储基本类型。大小不固定,可以动态变化,非常适合做元素的增删操作。  只能存储引用类型非要存储基本类型,选择包装类。

1.数组和集合的元素存储的个数问题。

数组定义后类型确定,长度固定

集合类型可以不固定,大小是可变的

2.数组和集合存储元素的类型问题

数组可以存储基本类型和引用类型的数据

集合只能存储引用类型的数据

3.数组和集合适用的场景

数组适合做数据个数和类型确定的场景(存储东南西北,存储男女)

集合适合做数据个数不确定,且要做增删元素的场景
 

集合的体系结构

先学单列集合

 List系列集合:有序、可重复、有索引

ArrayList、LinkedList: 有序、可重复、有索引

Set集合:添加的元素无序、不重复、无索引

HashSet 无序、不重复、无索引

LinkedSet有序、不重复、无索引

TreeSet按着大小默认升序、不重复、无索引

 如何约定集合存储的数据类型(集合支持泛型)

学习Collection的api,Collection是单列集合的祖宗,所有的单列集合都继承Collection的方法

  1. Collection<String> list = new ArrayList<>();
  2. //1.集合中添加元素,添加成功返回true,失败返回false
  3. list.add("java");
  4. list.add("Java");
  5. list.add("html");
  6. list.add("html");
  7. //2.清空元素
  8. list.clear();
  9. //3.判断是否为空
  10. list.isEmpty();
  11. //4.获取集合的大小
  12. list.size();
  13. //5.判断集合是否包含某元素
  14. list.contains("java");
  15. //6.删除集合的元素
  16. list.remove("java");
  17. // list.remove(2);不支持索引删除,只支持值删除
  18. //将集合转换成数组
  19. Object[] arr=list.toArray();

将集合转成数组,必须用Object来接收。

集合合并     集合1.addAll(集合2)  

  1. Collection<String> c1 = new ArrayList<>();
  2. c1.add("java");
  3. c1.add("html");
  4. Collection<String> c2= new ArrayList<>();
  5. c2.add("spring");
  6. c2.add("ssm");
  7. //把集合2中的元素合并到集合1,集合2中的元素也存在
  8. c1.addAll(c2);

Collection集合的遍历方式

1.第一种迭代器,取元素的时候c1.next() ,如果越界报异常NoSuchElementException

  1. Collection<String> c1 = new ArrayList<>();
  2. c1.add("java");
  3. c1.add("html");
  4. c1.add("css");
  5. //迭代器
  6. Iterator<String> iterator = c1.iterator();
  7. while(iterator.hasNext()){
  8. String next = iterator.next();
  9. System.out.println(next);
  10. }

2.第二种,foreach或者增强for循环,既可以遍历数组,也可以遍历集合。其内部原理是iterator迭代器

for(数据类型 变量名 : 数组或collection集合){

        //在此处使用变量

}

快捷键: 数组名或集合名.for

  1. Collection<String> c1 = new ArrayList<>();
  2. c1.add("java");
  3. c1.add("html");
  4. c1.add("css");
  5. //增强for
  6. for (String s : c1) {
  7. System.out.println(s);
  8. }

3.第三种 lambda表达式,通过调用forEach()方法,在方法中new Consumer

  1. Collection<String> c1 = new ArrayList<>();
  2. c1.add("java");
  3. c1.add("html");
  4. c1.add("css");
  5. //lambda表达式,通过调用forEach()方法来遍历
  6. c1.forEach(new Consumer<String>() {
  7. @Override
  8. public void accept(String s) {
  9. System.out.println(s);
  10. }
  11. });
  12. //上面代码简化成下面格式
  13. c1.forEach(s-> System.out.println(s));

Collection集合不支持for循环遍历,集合不能通过索引查找对象

集合中存储的是元素的地址


List集合因为支持索引,所以多了很多索引的api,其他Collection的功能也都继承。

  1. //list集合特点 有序 重复 有索引
  2. List<String> list=new ArrayList<>();
  3. list.add("java");
  4. list.add("java");
  5. list.add("html");
  6. list.add("spring");
  7. //1.在某个位置插入元素
  8. list.add(2,"ssm");
  9. //2.根据索引删除元素,返回被删除元素
  10. System.out.println(list.remove(1));
  11. //3.根据索引获取元素
  12. System.out.println(list.get(2));
  13. //4.修改索引位置的元素,返回被修改的元素
  14. System.out.println(list.set(2, "mybatis"));

List实现类的底层原理

ArrayList底层是基于数组实现的,查询速度快,增删慢。

LinkedList底层是基于双链表实现的,查询元素慢,增删首尾元素快。

List集合的遍历方式有四种

iterator、增强for、lambda表达式、for循环

写一下for循环就行,通过list.get(索引)  来遍历

  1. List<String> list=new ArrayList<>();
  2. list.add("java");
  3. list.add("java");
  4. list.add("html");
  5. list.add("spring");
  6. for (int i = 0; i < list.size(); i++) {
  7. String s = list.get(i);
  8. System.out.println(s);
  9. }

ArrayList集合底层原理

 List集合存储的元素超过容量后会扩容,扩容到原来的1.5倍。


 一些常用api

  1. //栈
  2. LinkedList<String> stack=new LinkedList<>();
  3. //压栈,入栈
  4. stack.addFirst("第一颗子弹");
  5. stack.push("第二颗子弹"); //用push代替addFirst,作用一样
  6. stack.push("第三颗子弹");
  7. System.out.println(stack);
  8. stack.removeFirst();
  9. stack.pop(); //用stack.pop代替removeFirst,作用一样
  10. System.out.println(stack);
  11. //队列
  12. LinkedList<String> queue=new LinkedList<>();
  13. //入队
  14. queue.addLast("1号");
  15. queue.addLast("2号");
  16. queue.addLast("3号");
  17. System.out.println(queue);
  18. //出队
  19. queue.removeFirst();
  20. queue.removeFirst();
  21. System.out.println(queue);

集合的并发修改异常问题

 必须用迭代器自带的remove,如果用集合的remove方法,会报错(并发修改异常),会漏删

  1. List<String> list = new ArrayList<>();
  2. list.add("java");
  3. list.add("java");
  4. list.add("html");
  5. list.add("ssm");
  6. Iterator<String> iterator = list.iterator();
  7. while(iterator.hasNext()){
  8. String next = iterator.next();
  9. if ("java".equals(next)){
  10. //list.remove("java") 会报错
  11. iterator.remove(); //保证不后移,会遍历到全部元素
  12. }
  13. }
  14. System.out.println(list);

不能用forEach遍历删除,Bug解决不了。

lambda也不能遍历删除,底层源码就是forEach

for循环正向着删除,也会漏删,但是不会报错。

  1. List<String> list = new ArrayList<>();
  2. list.add("html");
  3. list.add("ssm");
  4. list.add("java");
  5. list.add("java");
  6. for (int i = 0; i < list.size()-1; i++) {
  7. if("java".equals(list.get(i))){
  8. list.remove("java");
  9. }
  10. }
  11. System.out.println(list);

会漏删

for循环倒着遍历删除,不会出错

  1. List<String> list = new ArrayList<>();
  2. list.add("html");
  3. list.add("ssm");
  4. list.add("java");
  5. list.add("java");
  6. //倒着遍历不会出错
  7. for (int i = list.size()-1; i >=0; i--) {
  8. if("java".equals(list.get(i))){
  9. list.remove("java");
  10. }
  11. }
  12. System.out.println(list);

 for循环如果非要正向删除,在下面加上  i-- 就可以

  1. List<String> list = new ArrayList<>();
  2. list.add("html");
  3. list.add("ssm");
  4. list.add("java");
  5. list.add("java");
  6. for (int i = 0; i < list.size()-1; i++) {
  7. if("java".equals(list.get(i))){
  8. list.remove("java");
  9. }
  10. i--;
  11. }
  12. System.out.println(list);

泛型

 任意类型 + " "  都变成字符串类型

  1. double a= 1.0;
  2. String s=a+"";
  3. System.out.println(s);

泛型类、泛型接口、泛型方法

 

 泛型方法

 泛型方法用<T>修饰,定义的数组必须是引用类型。

  1. public static void main(String[] args) {
  2. Integer[] arr={2,4,6,3,1};
  3. printArray(arr);
  4. }
  5. public static <T> void printArray(T[] arr){
  6. if (arr !=null){
  7. StringBuilder sb=new StringBuilder("[");
  8. for (int i = 0; i <= arr.length - 1; i++) {
  9. sb.append(arr[i]).append(i == arr.length - 1 ? "" : ",");
  10. }
  11. sb.append("]");
  12. System.out.println(sb);
  13. }else{
  14. System.out.println(arr);
  15. }
  16. }

 泛型接口

 泛型接口的作用,可以让实现类选择当前功能需要操作的数据类型。

有Teacher类、Student类、Data接口、TeacherData实现类

 Data接口种的代码如下

 泛型通配符

?在使用泛型的时候代表一切类型。  泛型的上下限  ? extends Car    必须是Car或其子类

 ? super Car  必须是父类或Car

 


Set集合

 

 

 因为根据哈希值,可以快速的实现增删改查。

 

 

 

先根据哈希值取余,找到位置,再看位置是否为null,如果为null直接存入。不为null,用equals()方法比较内容是否一样。

Set集合去重复原因,先判断哈希值,在判断equals。Set集合里面存对象,如果对象中内容一样,set想要去掉重复的,必须在对象类中,重写hashcode()和equals()方法。

在没有在Student类中,重写equals()和

  1. Set<Student> set=new HashSet<>();
  2. Student s1=new Student("伽罗",20,170.0);
  3. Student s2=new Student("伽罗",20,170.0);
  4. Student s3=new Student("刘备",23,180.0);
  5. System.out.println(s1.hashCode());
  6. System.out.println(s2.hashCode());
  7. set.add(s1);
  8. set.add(s2);
  9. set.add(s3);
  10. System.out.println(set);

输出台中,hashcode值不一样,而且集合中存储两个伽罗信息

 

LinkedHashSet

TreeSet

 

 要想使用TreeSet存储自定义类型,需要指定排序规则。

 在对象类实现Comparable接口,重写compareTo方法时,要注意下面规则

 写一个Student类

  1. public class Student implements Comparable<Student>{
  2. private String name;
  3. private int age;
  4. private double height;
  5. public Student(String name, int age, double height) {
  6. this.name = name;
  7. this.age = age;
  8. this.height = height;
  9. }
  10. public Student() {
  11. }
  12. public String getName() {
  13. return name;
  14. }
  15. public void setName(String name) {
  16. this.name = name;
  17. }
  18. public int getAge() {
  19. return age;
  20. }
  21. public void setAge(int age) {
  22. this.age = age;
  23. }
  24. public double getHeight() {
  25. return height;
  26. }
  27. public void setHeight(double height) {
  28. this.height = height;
  29. }
  30. @Override
  31. public String toString() {
  32. return "Student{" +
  33. "name='" + name + '\'' +
  34. ", age=" + age +
  35. ", height=" + height +
  36. '}';
  37. }
  38. @Override
  39. public int compareTo(Student o) {
  40. return this.age-o.age;
  41. }
  42. }

在重写的方法中,return this.age - o.age;    如果有两个对象的年龄相等,会被TreeSet判定为两个相同的对象,就会去掉一个。

输出结果会这样显示

 重写的方法可以这样写,就只会返回两个值

  1. @Override
  2. public int compareTo(Student o) {
  3. return this.age-o.age >=0 ? 1:-1;
  4. }

第二种自定义规则的方法,用集合自带的比较器比较。

  1. public static void main(String[] args) {
  2. Set<Student> set=new TreeSet<>(new Comparator<Student>() {
  3. @Override
  4. public int compare(Student o1, Student o2) {
  5. return o1.getAge()-o2.getAge() >=0 ? 1:-1;
  6. }
  7. });
  8. Student s1=new Student("关羽",20,170.0);
  9. Student s2=new Student("伽罗",20,170.0);
  10. Student s3=new Student("刘备",23,180.0);
  11. set.add(s1);
  12. set.add(s2);
  13. set.add(s3);
  14. System.out.println(set);
  15. }

如果想通过身高去比较,用Double的api,Double.compare(o2.getHeigth(),o1.getHeight()) 这是降序

  1. Set<Student> set=new TreeSet<>(new Comparator<Student>() {
  2. @Override
  3. public int compare(Student o1, Student o2) {
  4. return Double.compare(o2.getHeight(),o1.getHeight());
  5. }
  6. });

用Double.compare()比较,当两个数值大小一样时,应该怎么办?

  1. import java.util.Arrays;
  2. public class Main {
  3. public static void main(String[] args) {
  4. double[] values = { 3.5, 2.0, 5.1, 3.5, 1.8 };
  5. Arrays.sort(values, (a, b) -> {
  6. int compareResult = Double.compare(a, b);
  7. if (compareResult != 0) {
  8. return compareResult;
  9. } else {
  10. // 在比较结果为0时,在这里添加其他排序条件
  11. // 例如,按照原始顺序保持相等值的相对顺序
  12. return 0; // 或者可以返回其他值进行排序
  13. }
  14. });
  15. // 输出排序结果
  16. for (double value : values) {
  17. System.out.println(value);
  18. }
  19. }
  20. }


可变参数

  1. public static void main(String[] args) {
  2. MethodSum(); //可以不传入参数
  3. MethodSum(1); //可以传1个参数
  4. MethodSum(2,3,4,5,6); //可以传多个参数
  5. }
  6. //一个方法只能传入一个可变参数
  7. //传入可变参数,必须放在其他参数后面
  8. //public static void MethodSum(int a,int...arr)
  9. public static void MethodSum(int...arr){
  10. //可变参数在方法本质就是一个数组
  11. System.out.println(arr.length);
  12. System.out.println(Arrays.toString(arr));
  13. }


 Collections集合工具类

快捷键  Shift+F6  选中一个名字后,可以一下全部改所有的名字

Collections几个常用的api

public static<T> boolean addAll(Collection<? super T>)给集合对象批量添加元素。

addAll中添加T类和他的子类都可以。

1.批量添加数据(给所有的Collection集合添加数据)

  1. public static void main(String[] args) {
  2. List<Integer> list=new ArrayList<>();
  3. list.add(2);
  4. list.add(89);
  5. list.add(34);
  6. list.add(6);
  7. Collections.addAll(list,2,3,4,5,11,6,100,0); //一行代码就搞定
  8. }

2.打乱List集合顺序

public static void shuffle (List<?> list) :打乱list集合顺序

Collections.shuffle();

3.对List集合排序

public static<T> void sort(List<T> list);

Collections.sort();  默认排有值特性的List,比如int类型

  1. List<Integer> list=new ArrayList<>();
  2. Collections.addAll(list,7,56,87,4,0,1);
  3. Collections.sort(list);
  4. System.out.println(list);

如果对自定义对象排序,除非有两种情况,第一种:对象类实现了Comparable接口,并重写了CompareTo方法,自定义了比较规则。

第二种:如下代码

  1. public static void main(String[] args) {
  2. List<People> list=new ArrayList<>();
  3. People p1=new People("伽罗",20,false);
  4. People p2=new People("刘备",23,true);
  5. People p3=new People("关羽",32,true);
  6. Collections.addAll(list,p1,p2,p3);
  7. Collections.sort(list, new Comparator<People>() { //自定义规则
  8. @Override
  9. public int compare(People o1, People o2) {
  10. return o1.getAge()-o2.getAge();
  11. }
  12. });
  13. System.out.println(list);
  14. }

斗地主案例

先定义一个Card类  (index的作用是给每个牌赋值,每张牌的真正大小)

  1. public class Card {
  2. private String size;
  3. private String color;
  4. private int index;
  5. public Card() {
  6. }
  7. public Card(String size, String color,int index) {
  8. this.size = size;
  9. this.color = color;
  10. this.index = index;
  11. }
  12. public String getSize() {
  13. return size;
  14. }
  15. public void setSize(String size) {
  16. this.size = size;
  17. }
  18. public String getColor() {
  19. return color;
  20. }
  21. public void setColor(String color) {
  22. this.color = color;
  23. }
  24. public int getIndex() {
  25. return index;
  26. }
  27. public void setIndex(int index) {
  28. this.index = index;
  29. }
  30. @Override
  31. public String toString() {
  32. return color+size;
  33. }
  1. public static ArrayList<Card> allCards=new ArrayList<>();
  2. static {
  3. String[] size = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
  4. String[] color = {"♥","♣","♠","♦"};
  5. for (String s : color) {
  6. int index=0;
  7. for (String s1 : size) {
  8. ++index; //每张牌都有索引值的大小
  9. Card c=new Card(s1,s,index);
  10. allCards.add(c);
  11. }
  12. }
  13. Card da = new Card("","
    声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小惠珠哦/article/detail/973982
    推荐阅读
    相关标签