集合

集合类特点:提供一种存储空间可变的存储模型,存储的数据容量可以随时发生改变

这里需要回顾一下,因为数组和字符串一旦创建,就不可改变,需要区分一下

  1. import java.util.ArrayList;
  2. import java.util.Collection;
  3. public class CollectionDemo {
  4. public static void main(String[] args) {
  5. Collection<String> c = new ArrayList<>();
  6. c.add("Hello");
  7. c.add("World");
  8. c.add("java");
  9. System.out.println(c);
  10. // 集合常用方法
  11. // 长度size
  12. System.out.println(c.size());
  13. // 添加add,上文已使用
  14. // 移除remove
  15. c.remove("hello");
  16. boolean hello = c.remove("Hello");
  17. System.out.println(hello);
  18. System.out.println(c);
  19. // 包含
  20. boolean world = c.contains("World");
  21. System.out.println(world);
  22. // 判空
  23. boolean empty = c.isEmpty();
  24. System.out.println(empty);
  25. // 清空
  26. c.clear();
  27. System.out.println(c);
  28. }
  29. }
  1. [Hello, World, java]
  2. 3
  3. true
  4. [World, java]
  5. true
  6. false
  7. []

用完之后发现这种多态方式使用Collection并不好用,不如直接使用ArrayList,而且ArrayList常用的5个方法更好用:addgetremovesetsize

如果想对Collection进行遍历,需要使用迭代器

Iterator是集合的专用遍历方式,Collection可以用,ArrayList之类的也可以用

常用3个方法:nexthasNextremove

  1. // Iterator的使用
  2. import java.util.ArrayList;
  3. import java.util.Collection;
  4. import java.util.Iterator;
  5. public class IteratorDemo {
  6. public static void main(String[] args) {
  7. Collection<String> c = new ArrayList<>();
  8. c.add("Hello");
  9. c.add("World");
  10. c.add("Java");
  11. c.add("100");
  12. // c.add("101");
  13. Iterator<String> iterator = c.iterator();
  14. while(iterator.hasNext()) {
  15. String s = iterator.next();
  16. //
  17. if(s.equals("100")){
  18. iterator.remove();
  19. System.out.println(s);
  20. // iterator.add("Java");
  21. }
  22. // System.out.println(iterator.next());
  23. }
  24. System.out.println(c);
  25. }
  26. }

要注意,Iterator没有add方法,强行使用会导致并发修改异常

List集合特点:

有序集合,可重复

并发修改异常:迭代器遍历过程中,通过集合对象修改了集合中元素长度,造成迭代器获取元素中判断预期修改值和实际修改值不一致。解决:使用for循环

  1. import java.util.ArrayList;
  2. import java.util.List;
  3. import java.util.ListIterator;
  4. public class ListIteratorDemo {
  5. public static void main(String[] args) {
  6. List<String> str = new ArrayList<>();
  7. str.add("Hello");
  8. str.add("World");
  9. str.add("Java");
  10. ListIterator<String> listIterator = str.listIterator();
  11. /*
  12. while(listIterator.hasPrevious()){
  13. // System.out.println(listIterator.previousIndex());
  14. // System.out.println(listIterator.previous());
  15. String previous = listIterator.previous();
  16. System.out.println(previous);
  17. }
  18. */
  19. while(listIterator.hasNext()){
  20. String next = listIterator.next();
  21. if(next.equals("Java")){
  22. listIterator.add("JavaEE");
  23. }
  24. }
  25. while(listIterator.hasPrevious()){
  26. System.out.println(listIterator.previousIndex());
  27. // System.out.println(listIterator.previous());
  28. String previous = listIterator.previous();
  29. System.out.println(previous);
  30. }
  31. }
  32. }
  1. 3
  2. JavaEE
  3. 2
  4. Java
  5. 1
  6. World
  7. 0
  8. Hello

ListIterator可以使用add方法,并且可以查看迭代器的索引

增强for循环

  • 目的:简化数组和Collection集合的遍历
  • 底层:Iterator,也就是不能使用add方法
  • 格式:for(元素数据类型变量名:数组或者Collection集合){//使用变量}
  1. public class ForDemo {
  2. public static void main(String[] args) {
  3. int [] arr = {1,2,3,4,5};
  4. for(int i:arr){
  5. System.out.println(i);
  6. }
  7. }
  8. }

数据进入栈模型的过程称为:压/进栈,反之为弹/出栈

栈是先进后出的模型

队列

入队/出队

队列是先进先出的模型

数组

查询数据通过索引定位,查询效率高

删除和添加效率低

链表

增删快,查询慢

ArrayList

ArrayList是List接口的可调整大小的数组实现,数组特点是查询快,增删慢

LinkList

LinkList是双链表实现List和Deque接口,查询慢,增删快

常用方法:addFirstaddLastgetFirstgetLastremoveFirstremoveLast

居然还可以在指定位置插入元素

    • add(int index, E element) 在列表中指定的位置上插入指定的元素。

Set

不包含重复元素的集合,且没有带索引的方法,不能使用普通for循环遍历

HashSet

对集合的迭代顺序不作任何保证

hashCode方法,默认情况下,不同对象的hash值不同

  1. // Student类
  2. public class Student {
  3. private int age;
  4. public Student() {
  5. }
  6. public Student(int age) {
  7. this.age = age;
  8. }
  9. public int getAge() {
  10. return age;
  11. }
  12. public void setAge(int age) {
  13. this.age = age;
  14. }
  15. }
  1. // 测试类
  2. import java.util.HashSet;
  3. import java.util.Set;
  4. public class My_Hash {
  5. public static void main(String[] args) {
  6. Set<String> s1 = new HashSet<>();
  7. s1.add("java");
  8. Set<String> s2 = new HashSet<>();
  9. s2.add("java");
  10. System.out.println(s1.hashCode());
  11. System.out.println(s2.hashCode());
  12. System.out.println("--------");
  13. Student s3 = new Student(18);
  14. Student s4 = new Student(18);
  15. System.out.println(s3.hashCode());
  16. System.out.println(s4.hashCode());
  17. }
  18. }
  1. 3254818
  2. 3254818
  3. --------
  4. 1324119927
  5. 990368553

但是可以在原来的类中重写hashCode方法,这样就可以返回指定hash值

如在上述学生类中重写hashCode方法如下

  1. @Override
  2. public int hashCode(){
  3. return age;
  4. // return 0;
  5. }

这样返回的hash值就都为自己创建对象的age值

HashSet

  • 底层数据结构是哈希表
  • 对集合的迭代顺序不作任何保证
  • 没有索引方法,所以不能使用普通for循环遍历
  • 不包含重复元素的集合

哈希表

LinkedHashSet

有哈希表和链表实现的Set接口,具有可预测的迭代次序

由链表保证元素有序,也就是说元素的存储和取出的顺序是一致的,这点和HashSet不同

由哈希表保证元素唯一性

TreeSet

元素按照一定的规则进行排序,无参构造方法按照自然顺序排序,带参构造方法按照指定规则排序

要进行自然排序,需Comparable或者Comparator

  • Comparable:此接口对实现它的每个类的对象进行了总排序。这个顺序被称为类的空自然排序,和类的 compareTo方法称为空自然比较方法。
  • 一个比较函数,这对一些对象的集合,对总序。比较器可以通过某种方法(如 Collections.sort或 Arrays.sort)允许在排序顺序的精确控制。比较器也可以用来控制特定的数据结构顺序(如 sorted sets或 sorted maps),或提供的对象不集合排序有 natural ordering。

首先看一下TreeSet对Integer进行自然排序

  1. import java.util.TreeSet;
  2. public class Demo {
  3. public static void main(String[] args) {
  4. TreeSet<Integer> ts = new TreeSet<>();
  5. ts.add(5);
  6. ts.add(10);
  7. ts.add(1);
  8. ts.add(7);
  9. ts.add(20);
  10. for(int i:ts){
  11. System.out.println(i);
  12. }
  13. }
  14. }
  1. 1
  2. 5
  3. 7
  4. 10
  5. 20

这是因为Integer实现了Comparable接口,不能想当然认为其他类也实现了

    1. public final class Integer
    2. extends Number
    3. implements Comparable<Integer>

接下来对一般类实现自然排序

  1. // 学生类
  2. public class Student implements Comparable{
  3. private String name;
  4. private int age;
  5. public Student(String name, int age) {
  6. this.name = name;
  7. this.age = age;
  8. }
  9. public Student() {
  10. }
  11. public String getName() {
  12. return name;
  13. }
  14. public void setName(String name) {
  15. this.name = name;
  16. }
  17. public int getAge() {
  18. return age;
  19. }
  20. public void setAge(int age) {
  21. this.age = age;
  22. }
  23. @Override
  24. public String toString() {
  25. return "Student{" +
  26. "name='" + name + '\'' +
  27. ", age=" + age +
  28. '}';
  29. }
  30. @Override
  31. public int compareTo(Object o) {
  32. // return 0;
  33. return 1;
  34. }
  35. }
  1. // 测试类
  2. public class Demo {
  3. public static void main(String[] args) {
  4. TreeSet<Student> s = new TreeSet<>();
  5. Student s1 = new Student("linqingxia",18);
  6. Student s2 = new Student("zhangmanyu",48);
  7. Student s3 = new Student("wangzuxian",38);
  8. Student s4 = new Student("zhangmin",28);
  9. s.add(s1);
  10. s.add(s2);
  11. s.add(s3);
  12. s.add(s4);
  13. for(Student st:s){
  14. System.out.println(st);
  15. }
  16. }
  17. }

继承Comparale,再重写CompareTo方法

        1. int compareTo(T o)
        2. ```
        3. 将此对象与指定的对象进行比较,以。返回一个负整数、零或一个正整数,因为这个对象小于、等于或大于指定的对象。

如果想要按照年龄进行排序,则需要把CompareTo进行如下改写

  1. public class Student implements Comparable<Student>{
  2. private String name;
  3. private int age;
  4. public Student(String name, int age) {
  5. this.name = name;
  6. this.age = age;
  7. }
  8. public Student() {
  9. }
  10. public String getName() {
  11. return name;
  12. }
  13. public void setName(String name) {
  14. this.name = name;
  15. }
  16. public int getAge() {
  17. return age;
  18. }
  19. public void setAge(int age) {
  20. this.age = age;
  21. }
  22. @Override
  23. public String toString() {
  24. return "Student{" +
  25. "name='" + name + '\'' +
  26. ", age=" + age +
  27. '}';
  28. }
  29. @Override
  30. public int compareTo(Student s) {
  31. // return 0;
  32. int num1 = this.age - s.age;
  33. int num2 = num1 == 0?this.name.compareTo(s.name):num1;
  34. return num2;
  35. }
  36. }
  1. import java.util.TreeSet;
  2. public class Demo {
  3. public static void main(String[] args) {
  4. TreeSet<Student> s = new TreeSet<>();
  5. Student s1 = new Student("linqingxia",18);
  6. Student s2 = new Student("zhangmanyu",48);
  7. Student s3 = new Student("wangzuxian",38);
  8. Student s4 = new Student("zhangmin",28);
  9. Student s5 = new Student("qiushuzhen",28);
  10. s.add(s1);
  11. s.add(s2);
  12. s.add(s3);
  13. s.add(s4);
  14. s.add(s5);
  15. for(Student st:s){
  16. System.out.println(st);
  17. }
  18. }
  19. }

TreeSet结合存储自定义对象时,带参构造方法使用比较器排序对元素进行排序

同样,也可以让类继承Compareble,然后重写CompareTo来实现

上例中implements Compareble<Student>是因为测试类中使用的是泛型

题目:用TreeSet集合存储多个学生信息(姓名,语文成绩,数学成绩),并遍历该集合,要求:按照总分从高到底出现

为了简化,就不写get和set方法

  1. // 学生类
  2. public class Student implements Comparable<Student>{
  3. private String name;
  4. private int mathScore;
  5. private int chinesScore;
  6. private int englishScore;
  7. public int setTotalScore(){
  8. return mathScore+chinesScore+englishScore;
  9. }
  10. public Student(String name, int mathScore, int chinesScore, int englishScore) {
  11. this.name = name;
  12. this.mathScore = mathScore;
  13. this.chinesScore = chinesScore;
  14. this.englishScore = englishScore;
  15. }
  16. public Student() {
  17. }
  18. @Override
  19. public String toString() {
  20. return "Student{" +
  21. "name='" + name + '\'' +
  22. ", mathScore=" + mathScore +
  23. ", chinesScore=" + chinesScore +
  24. ", englishScore=" + englishScore +
  25. ", totalScore=" + setTotalScore() +
  26. '}';
  27. }
  28. @Override
  29. public int compareTo(Student student) {
  30. int num1 = student.setTotalScore() - this.setTotalScore();
  31. int num2 = num1 == 0?student.mathScore-this.mathScore:num1;
  32. int num3 = num2 == 0?student.chinesScore-this.chinesScore:num2;
  33. int num4 = num3 == 0?student.englishScore-this.englishScore:num3;
  34. int num5 = num4 == 0?student.name.compareTo(this.name):num4;
  35. return num5;
  36. }
  37. }
  1. // 测试类
  2. import java.util.TreeSet;
  3. public class Demo {
  4. public static void main(String[] args) {
  5. TreeSet<Student> ts = new TreeSet<>();
  6. Student s1 = new Student("赵",99,98,99);
  7. Student s2 = new Student("钱",98,99,100);
  8. Student s3 = new Student("孙",99,98,100);
  9. Student s4 = new Student("李",100,99,98);
  10. ts.add(s1);
  11. ts.add(s2);
  12. ts.add(s3);
  13. ts.add(s4);
  14. for(Student s:ts){
  15. System.out.println(s);
  16. }
  17. }
  18. }

包装类如Integer和String是实现了Compareble的,所以可以直接使用CompareTo方法

Java学习笔记-基础语法Ⅶ-集合的更多相关文章

  1. Java学习笔记-基础语法Ⅳ

    多态:同一个对象,在不同时刻表现出来的不同形态 例如: 猫 cat = new 猫(); 动物 animal = new 猫(); 这里的猫在不同时刻表现出来不同的形态,这就是多态 多态的前提和体现: ...

  2. Java学习笔记-基础语法Ⅷ-泛型、Map

    泛型 泛型本质上是参数化类型,也就是说所操作的数据类型被指定为一个参数,即将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型,这种参数类型可以用在类.方法和接口中,分别为泛型类.泛型方法 ...

  3. Java学习笔记-基础语法Ⅴ

    学习一些Java常用的API Math:包含执行基本数字运算的方法 如果没有构造方法,一般类的成员都是静态的,通过类名可以直接调用 Java中有两种random函数,Math.Random()函数能够 ...

  4. Java学习笔记-基础语法

    Java基础包含关键字,标识符,注释,常量和变量,运算符 关键字 关键字的定义和特点 定义:被Java语言赋予了特殊含义的单词 特点:关键字中所有字母都为小写 Java的关键字 用于定义数据类型的关键 ...

  5. Java学习笔记-基础语法Ⅹ-进程线程

    学习快一个月了,现在学到了黑马Java教程的300集 打印流的特点: 只负责输出数据,不负责读取数据 有自己的特有方法 字节打印流:PrintStream,使用指定的文件名创建新的打印流 import ...

  6. Java学习笔记-基础语法Ⅱ

    成员变量:类中方法外的变量 局部变量:方法中的变量 注意,成员变量有默认初始值,而局部变量需要赋初始值 Java中虽然没有明确规定类必须首字母大写,但为了规范最好大写(因为自己刚刚写的时候就没看清写错 ...

  7. JAVA 学习笔记 - 基础语法 2

    ---恢复内容开始--- 1.数组的申明和应用 数据类型 数组名称[] = null;             //在堆栈中申明变量名称 数组名称 =  new  数据类型[10];       // ...

  8. JAVA 学习笔记 - 基础语法1

    1. 类的定义 public class  与  class的区别 一个java文件只有一个public class, 而且类名必须与文件名一致. 一个java文件可以有多个class定义,javac ...

  9. Java学习笔记-基础语法ⅩⅠ-UDP、TCP

    网络编程 三要素:IP地址.端口.协议 IP地址:使用ipconfig查看,如果装了VM的话,会有VMnet1.VMnet8和WLAN,net1不能从虚拟机到主机,net8不能从主机到虚拟机,net0 ...

随机推荐

  1. JavaScript 表单事件

    表单事件,当用户与表单元素进行交互时发生. 实例: 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>表单事件& ...

  2. 剑指Offer30——包含min函数的栈

    剑指Offer30--包含min函数的栈 1. 题目简述 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数在该栈中,调用min.push及pop的时间复杂度是O(1). 2. 题 ...

  3. c++ 虚函数多态、纯虚函数、虚函数表指针、虚基类表指针详解

    静态多态.动态多态 静态多态:程序在编译阶段就可以确定调用哪个函数.这种情况叫做静态多态.比如重载,编译器根据传递给函数的参数和函数名决定具体要使用哪一个函数.动态多态:在运行期间才可以确定最终调用的 ...

  4. Visual Studio Code 快捷键大全(最全)

    Visual Studio Code 是一款优秀的编辑器,对于开发前端带来了很多便利,熟悉快捷键的使用,能够起到事半功倍的作用,提高工作效率.下面就Visual Studio Code常用快捷键的一些 ...

  5. CSS学习(二):背景图片如何定位?

    我们都知道background-position属性用来指定背景图片应该出现的位置,可以使用关键字.绝对值和相对值进行指定.在CSS Sprites中,这个属性使用比较频繁,使用过程中,我常混淆,经常 ...

  6. x64 番外篇——保护模式相关

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...

  7. python爬虫---表情包批量采集

    代码: import requests from pyquery import PyQuery as pq # 比xpath还要灵活的html解析工具 # 定义请求 headers = { " ...

  8. 【Android开发】毛玻璃效果

    使用一:静态控件上使用 先附上自定义view-BlurringView public class BlurringView extends View { private int mDownsample ...

  9. java中抽象类和抽象方法到底什么关系?请举例说明!

    抽象类和抽象方法什么关系?抽象类中可能有抽象方法,也可能没有抽象方法.那位说,就跟没说一样,那抽象类和抽象方法都叫抽象,他们必定有关系,那关系是什么呢?如果一个类中有抽象方法,它必须得是抽象类. An ...

  10. mysql数据乱码

    更改数据库安装时的字符编码.打开mysql安装目录,找到my.ini文件,通过使用记事本的方式打开,将这里面的default-character-set=latin1修改成gbk,注意这里面有两处需要 ...