Java进阶第三天

1、List集合

1.1 List
1、List集合的常用方法
   boolean add(E e);
   E remove(index i);
2、ArrayList集合是List集合的一个可变大小的数组实现
3、底层是一个数组,数组查询快,因为地址连续,且有索引;增删慢,因为地址不连续,每次增删要创建一个新数组
public class Demo01List {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();//多态
    //add方法
    list.add(“a”);
    list.add(“b”);
    list.add(“c”);
    list.add(“d”);
    list.add(“e”);
    System.out.println(list);
    //remove方法 删除a时,若集合中存在两个a,只会删除前一个
    String removeE = list.remove(3);
    System.out.println(“被移除的元素是:” + removeE + “当前集合:” + list);
    //set方法
    String replaceE = list.set(3, “E”);
    System.out.println(“被替换的元素是:” + replaceE + “当前集合:” + list);
    //get方法
    //遍历集合 法一
    for (int i = 0; i < list.size(); i++) {
      System.out.println(list.get(i));
    }
    //法二
    Iterator it = list.iterator();
    while (it.hasNext()) {
      System.out.println(it.next());
    }
    //法三
    for (String s : list) {
      System.out.println(s);
    }
  }
}
1.2 LinkedList
1、LinkedList是List的一个链表实现
2、底层是一个双向链表,查询慢,因为地址不连续,要从头开始查询,但找头节点和尾节点很快;增删快,因为增删操作不影响整个链表
3、不能使用多态创建对象,否则用不了子类方法
public class Demo02LinkedList {
  public static void main(String[] args) {
    LinkedList<String> list = new LinkedList<>();
    //添加元素的方法
    //add方法
    list.add(“a”);
    list.add(“b”);
    list.add(“c”);
    System.out.println(list);
    //addFirst方法
    list.addFirst(“first”);
    System.out.println(list);
    //push方法,等价于addFirst方法
    list.push(“second”);
    System.out.println(list);
    //addLast方法,等价于add方法
    list.addLast(“last”);
    System.out.println(list);
 
    //获取元素的方法
    //getFirst方法
    //list.clear();//清空集合后获取元素会抛出异常NoSuchElementException,为了避免异常可以设置一个判断
    if (!list.isEmpty()) {
      String first = list.getFirst();
      System.out.println(first);
      //getLast方法
      String last = list.getLast();
      System.out.println(last);
    }
 
    //删除元素的方法
    //removeFirst方法
    String first = list.removeFirst();
    System.out.println(first);
    //removeLast方法
    String last = list.removeLast();
    System.out.println(last);
    //pop方法,等价于removeFirst方法
    String pop = list.pop();
    System.out.println(pop);
    System.out.println(list);
  }
}

2、Set集合

2.1 Set
1、特点:(1)不能存储重复元素
     (2)不带索引,没有带索引的方法,不能使用普通for循环遍历
2、Set接口的方法和Collection接口的方法一样
3、不能存储重复元素的原理:
    在调用add方法时,会调用hashCode方法和equals方法,判断元素是否重复
    前提:存储的元素必须重写hashCode方法和equals方法,保证元素不重复
    哈希值一样是哈希冲突
public class Demo01Set {
  public static void main(String[] args) {
    HashSet<String> set = new HashSet<>();
    String s1 = “abc”;
    String s2 = “abc”;
    set.add(s1);//add方法会调用hashCode方法计算"abc"的哈希值96354,在数组中找有没有存储该哈希值的元素,没有就把96354存进数组,并将s1链接到该元素下面,即存进集合
    set.add(s2);//add方法会调用hashCode方法计算"abc"的哈希值96354,在数组中找有没有存储该哈希值的元素。有就调用equals方法和哈希值相同的元素进行比较,s2.equals(s1),返回true,则认定两元素相同,就不存储s2到集合中
    set.add(“重地”);//add方法会调用hashCode方法计算"重地"的哈希值1179395,在数组中找有没有存储该哈希值的元素,没有就把1179395存进数组,并将"重地"链接到该元素下面,即存进集合
    set.add(“通话”);//add方法会调用hashCode方法计算"abc"的哈希值1179395,在数组中找有没有存储该哈希值的元素。有就调用equals方法和哈希值相同的元素进行比较,“通话”.equals(“重地”),返回false,则认定两元素不相同,就将"通话"链接到"重地"下面,即存进集合
    set.add(“abc”);
    System.out.println(set);//[重地, 通话, abc]
  }
}
2.2 HashSet
1、底层是哈希表结构,查询速度非常快
2、无序,存储和取出元素的顺序可能不一致
3、实现不同步,支持多线程,速度比较快
4、jdk1.8之前,哈希表=数组+链表 数组初始容量为16 数组里存储元素的哈希值,相同哈希值的元素链接在该哈希值所在数组位置的下面
  jdk1.8之后,哈希表=数组+链表/红黑树(链表长度超过8位,就会转换为红黑树)
new的是HashMap中的K,键唯一,所以不能存储相同元素
public class Demo02HashSet {
  public static void main(String[] args) {
    Set<Integer> set = new HashSet<>();//多态
    //add方法
    set.add(2);
    set.add(1);
    set.add(3);
    set.add(1);
    //使用迭代器遍历
    Iterator<Integer> it = set.iterator();
    while (it.hasNext()) {
      Integer i = it.next();
      System.out.println(i);//123 无序,且不能存储相同元素
    }
    //使用增强for遍历
    for (Integer integer : set) {
      System.out.println(integer);//123
    }
  }
}
2.3 哈希值
1、哈希值:一个十进制整数,由系统随机给出,就是对象的地址值,但是是一个逻辑地址,是模拟出来的地址,不是数据实际存储的物理地址
2、Object类中有一个获取对象哈希值的方法,public native int hashCode();没有方法体,调用本地操作系统的方法
Person类
public class Person {
}
测试类
public class Demo03HashValue {
  public static void main(String[] args) {
    Person p1 = new Person();//Person类默认继承Object,所以可以调用Object的hashCode方法
    int h1 = p1.hashCode();
    System.out.println(h1);//2083562754 随机十进制整数
    System.out.println(p1);//cn.ircast.demo02Set.Person@7c30a502 toString方法最后的值就是哈希值 7c30a502与2083562754相等
    //可以重写hashCode方法,返回一个常数,但这不代表两个对象的地址相等,因为这不是实际的物理地址
    //String类就重写了hashCode方法,当两个字符串的内容一样,返回的哈希值也一样
    String s1 = “asd”;
    String s2 = “asd”;
    System.out.println(s1.hashCode());//96882
    System.out.println(s2.hashCode());//96882
    System.out.println(“重地”.hashCode());//1179395
    System.out.println(“通话”.hashCode());//1179395
  }
}
2.4 HashSet存储我们自定义的类型的元素
让HashSet存储我们自定义的类型元素,必须重写hashCode和equals方法,不使用Set集合,可以不重写
同名同年龄的学生,视为同一元素
定义学生类
public class Student {
  private String name;
  private int age;
 
  @Override
  public String toString() {
    return “Student{” +
       “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;
  }

public Student(String name, int age) {
    this.name = name;
    this.age = age;
  }
 
  public Student() {
  }
 
  @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 &&
       Objects.equals(name, student.name);
  }
 
  @Override
  public int hashCode() {
    return Objects.hash(name, age);
  }
}
定义测试类使用HashSet存储学生类的元素
public class Demo04HashSetCustomize {
  public static void main(String[] args) {
    HashSet<Student> set = new HashSet<>();
    Student s1 = new Student(“张三”, 18);
    Student s2 = new Student(“张三”, 18);
    Student s3 = new Student(“李四”, 19);
    set.add(s1);
    set.add(s2);
    set.add(s3);
    System.out.println(set);
    //不重写hashCode方法的话,两个对象的哈希值不同
    //不重写equals方法的话,比较两个对象的地址值,也就是哈希值
    // [Student{name=‘张三’, age=18}, Student{name=‘张三’, age=18},Student{name=‘李四’, age=19}]
    //重写后[Student{name=‘张三’, age=18}, Student{name=‘李四’, age=19}]
  }
}
2.5 LinkedHashSet
  特点:底层是一个哈希表(数组+链表/红黑树)+链表,多了一条链表,用来记录元素的存储顺序,保证元素有序
public class Demo05LinkedHashSet {
  public static void main(String[] args) {
    HashSet<String> set1 = new HashSet<>();
    set1.add(“hello”);
    set1.add(“world”);
    set1.add(“java”);
    System.out.println(set1);//[world, java, hello] 无序
 
    LinkedHashSet<String> set2 = new LinkedHashSet();
    set2.add(“hello”);
    set2.add(“world”);
    set2.add(“java”);
    System.out.println(set2);//[hello, world, java] 有序
  }
}
2.6 可变参数
1、当方法的参数列表的数据类型确定,而参数个数不确定就可以使用可变参数
   修饰符 返回值类型 方法名(数据类型…变量名){}
2、底层是一个数组,根据传递的参数个数的不同,创建不同大小的数组,来存储这些参数,可以是0个参数
3、注意:
  (1)一个方法的参数列表只能有一个可变参数
  (2)可变参数要写在参数列表的末尾
public class Demo06VariablePara {
  public static void main(String[] args) {
    System.out.println(add());//0 创建一个长度为0的数组
    System.out.println(add(10));//10 创建一个长度为1的数组
    System.out.println(add(10, 20));//30
    System.out.println(add(10, 20, 30));//60
  }
  //计算0-n个整数的和
  public static int add(int…arr) {//arr存储的是数组的地址
    int sum = 0;
    for (int i = 0; i < arr.length; i++) {
      sum += arr[i];
    }
    return sum;
  }
  //可变参数的终极写法
  public static void method(Object…o) {//可以接收任意类型的参数
  }
}

3、集合工具类Collections

常用方法
  static boolean addAll(Collection c, T…elements)//往集合中添加一些元素
  static void shuffle(List<?> list)//打乱集合顺序
  static void sort(List list)//给集合按默认规则排序,升序
  static void sort(List list, Comparator<? super T>)//给集合按指定规则排序
    要对自定义类型进行排序,需要实现Comparable接口,重写compareTo方法,定义排序规则
    Comparable 自己和别人比较,自己需要实现Comparable接口,重写compareTo方法,定义比较规则
    Comparator 找一个第三方比较二者
Person类
不使用Set集合,可以不重写hashCode方法和equals方法
要调用Collections类的sort方法,必须实现Comparable接口,重写compareTo方法
public class Person implements Comparable {
  private String name;
  private int age;
 
  public Person() {
  }
 
  public Person(String name, int age) {
    this.name = name;
    this.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 String toString() {
    return “Person{” +
       “name=’” + name + ‘’’ +
       “, age=” + age +
       ‘}’;
  }
 
  @Override
  public int compareTo(Person o) {
    //return 0;//认为元素都是相同的
    //自定义比较规则
    return this.getAge() - o.getAge();//升序
  }
}
测试类
public class Demo01CollectionsMethod {
  public static void main(String[] args) {
    ArrayList list = new ArrayList<>();
 
    //addAll方法
    Collections.addAll(list, “hello”, “world”, “like”, “java”);
    System.out.println(list);//[hello, world, like, java]
 
    //shuffle方法
    Collections.shuffle(list);
    System.out.println(list);//[world, hello, java, like]
 
    //sort方法,默认排序,只能对List排序,不能对Set排序
    //Collections.sort(list);
    //System.out.println(list);//[hello, java, like, world]
 
    //对自定义的类型进行排序
    ArrayList list1 = new ArrayList<>();
    Collections.addAll(list1, new Person(“张三”, 18), new Person(“李四”, 17), new Person(“王五”, 20), new Person(“刘六”, 18));
    System.out.println(list1);//[Person{name=‘张三’, age=18}, Person{name=‘李四’, age=17}, Person{name=‘王五’, age=20}]
    //Collections.sort(list1);
    //System.out.println(list1);//[Person{name=‘李四’, age=17}, Person{name=‘张三’, age=18}, Person{name=‘王五’, age=20}]
 
    Collections.sort(list, new Comparator() {
      @Override
      public int compare(String o1, String o2) {
        return o1.compareTo(o2);
      }
    });
    System.out.println(list);

// Collections.sort(list1, new Comparator() {
    // @Override
    // public int compare(Person o1, Person o2) {
    // return o1.getAge() - o2.getAge();//升序
    // }
    // });
    Collections.sort(list1, new Comparator() {
      @Override
      public int compare(Person o1, Person o2) {
        int result = o1.getAge() - o2.getAge();
        if(result == 0) {//年龄相等,比较姓名字符串
          return o1.getName().compareTo(o2.getName());
        }
      return result;
      }
    });
    System.out.println(list1);
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值