java集合二:List & Set

在这里插入图片描述

一、List集合接口

package com.company.list;
/*
    List集合储存元素特点:
        1、有序(List集合中存储元素有下标)
        2、可重复

*/
import java.util.*;
public class ListTest01 {
    public static void main(String[] args) {

        // 创建一个List集合
        List l = new ArrayList();

        // 添加
        l.add(100);
        l.add(90);
        l.add(250);
        l.add(250);

        // 遍历
        Iterator it = l.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }

    }
}

package com.company.list;
/*
    深入List集合

    ArrayList集合底层是数组。数组是有下标的,所以ArrayList集合有很多自己的特性。

    ArrayList集合底层默认初始化容量是10,扩大之后的容量是原容量的1.5倍。
    Vector集合底层默认容量也是10,扩大之后的容量是原容量的2倍。

    LinkeList是链表,初始化容量就只有一个头节点

    如何优化ArrayList和Vector?
        尽量减少扩容操作,因为扩容需要数组拷贝。数组拷贝很耗内存。
        一般推荐在创建集合的时候指定初始化容量。
        List l = new ArrayList(50);  // 初始化容量为50,如果不写就默认为10

*/
import java.util.*;
public class ListTest02 {
    public static void main(String[] args) {

        // 创建List集合
        //List l = new ArrayList();
        List l = new LinkedList();
        // 这就是面向抽象编程的好处,ArrayList和LinkedList底层实现结构完全不一样
        // 但是由于他们实现的都是List接口,里面都可以使用相同的方法

        // 添加元素
        l.add(123);
        l.add(312);
        l.add(69);

        // 在下标为1的位置上添加555
        l.add(1, 555);

        // 取得第一个元素
        System.out.println(l.get(0));

        System.out.println("===========================");

        // 遍历(List集合特有的遍历方式)
        for(int i=0; i<l.size(); i++){
            Object element = l.get(i);
            System.out.println(element);
        }

        System.out.println("==========================");

        // 迭代器也可以实现List集合遍历
        Iterator it = l.iterator();
        while(it.hasNext()){
            Object element = it.next();
            System.out.println(element);
        }


    }
}

二、Set集合接口

2.1 hashSet集合
package com.company.set;
/*
    Set集合:HashSet

    1、HashSet底层实际上是一个HashMap,HashMap底层采用了哈希表数据结构。

    2、哈希表又叫做散列表,哈希表底层是一个数组,这个数组中每一个元素又是一个单向链表。
    每一个单向链表都有独一无二的hash值,代表数组的下标。在某一个单向链表中的每一个节点
    的hash值是相等的。hash值实际上是key调用hashCode方法,再通过“hash function”
    转换成的值。

    3、如何向哈希表中添加元素?
        先调用被储存元素的key的hashCode方法,经过某个算法得出hash值,如果在这个哈
      希表中不存在这个hash值,则直接加入元素。如果该hash值已经存在,继续调用key值之
      间的equals方法,如果equals方法返回false,则将该元素添加。如果equals返回true,
      则放弃添加该元素。

    4、HashSet其实是HashMap中的key部分。HashSet有什么特点,HashMap中的key应该
      有相同的特点。

    5、HashMap和HashSet初始化容量都是16,默认加载因子是0.75(当存储的元素达到整个数组
    的75%,就需要考虑扩容了)。
*/
import java.util.*;
public class SetTest01 {
    public static void main(String[] args) {

        // 创建Set集合
        Set s = new HashSet();

        // 无序不可重复
        s.add(1);
        s.add(100);
        s.add(250);
        s.add(88);
        s.add(85);
        s.add(1);

        // 遍历
        Iterator it = s.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
}

package com.company.set;
/*
    关于往Set集合中存储的元素,该元素的hashCode和equals方法。

    HashMap中有一个put方法,put(key, value) key是无序不可重复的。

    结论:存储在HashSet集合或者HashMap集合key部分的元素,需要同时重写hashCode + equals方法
*/
import java.util.*;
public class SetTest02 {
    public static void main(String[] args){

        // 创建集合
        Set s = new HashSet();

        Employee e1 = new Employee("1000", "Jack");
        Employee e2 = new Employee("1000", "Jack");
        Employee e3 = new Employee("2000", "Tom");
        Employee e4 = new Employee("2001", "King");
        Employee e5 = new Employee("3000", "Tony");
        Employee e6 = new Employee("3001", "Smith");

        // 虽然e1和e2 no和name都一样,但是由于都是new的对象,内存地址肯定不一样。
        // 在未重写hashCode()方法之前hash值肯定不同
        System.out.println(e1.hashCode());
        System.out.println(e2.hashCode());


        // 添加元素
        s.add(e1);
        s.add(e2);
        s.add(e3);
        s.add(e4);
        s.add(e5);
        s.add(e6);

        // 查看集合元素个数
        // 尽管e1和e2内容完全一致,但是由于hash值不同,添加元素时仍作为两个不同元素,显然不符合业务逻辑。
        // 因此需要重写Employee类中hashCode()方法
        System.out.println(s.size());

    }
}

// 根据现实的业务逻辑:该公司员工编号是:1000-9999
class Employee{

    // 编号
    String no;
    // 姓名
    String name;

    // Constructor
    public Employee(String no, String name){
        this.name = name;
        this.no = no;
    }

    // 重写equals方法
    // 如果员工编号相同,并且名字相同,则是同一个对象
    public boolean equals(Object o){
        if(this==o){
            return true;
        }
        if(o instanceof Employee){
            Employee e = (Employee)o;
            if(e.name.equals(this.name) && e.no.equals(this.no)){
                return true;
            }
        }

        return false;
    }


    // 重写hashCode方法
    public int hashCode(){
        // 以员工编号分组
        // 可以根据员工编号1000~9999,进行均匀分组
        // 例如1000~1999返回一个相同的hash值,2000~2999返回一个hash值...

        // 这里就直接调用String重写之后的hashCode()方法
        return no.hashCode();

    }
}
2.2 SortedSet集合
package com.company.sortedSet;
/*
    java.util.Set;  接口
        java.util.SortedSet;  接口,存储元素无序不可重复,但是存进去的元素可以按照元素大小顺序自动排序。
            java.util.TreeSet;  实现类
*/

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class SortedSetTest01{
    public static void main(String[] args) throws ParseException{

        // 创建元素
        SortedSet ss = new TreeSet();

        // 添加元素
        ss.add(10);  // 自动装箱
        ss.add(8);
        ss.add(78);
        ss.add(56);
        ss.add(24);
        ss.add(63);
        ss.add(9);

        // 遍历
        Iterator it = ss.iterator();

        while (it.hasNext()) {
            Object element = it.next();
            System.out.println(element); // 8 9 10 24 56 63 78
        }

        // String
        SortedSet strs = new TreeSet();

        strs.add("Jack");
        strs.add("Tom");
        strs.add("Cook");
        strs.add("Lucy");
        strs.add("Zoom");
        strs.add("Tony");

        it = strs.iterator();
        while (it.hasNext()) {
            Object element = it.next();
            System.out.println(element); // Cook Jack King Lucy Tom Tony
        }

        // 日期Date
        String st1 = "2008-08-08";
        String st2 = "2007-01-03";
        String st3 = "2012-03-21";
        String st4 = "2009-05-01";
        String st5 = "2013-08-22";
        String st6 = "2008-04-02";

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");


        Date t1 = sdf.parse(st1);
        Date t2 = sdf.parse(st2);
        Date t3 = sdf.parse(st3);
        Date t4 = sdf.parse(st4);
        Date t5 = sdf.parse(st5);
        Date t6 = sdf.parse(st6);


        // 添加
        SortedSet times = new TreeSet();

        times.add(t1);
        times.add(t2);
        times.add(t3);
        times.add(t4);
        times.add(t5);
        times.add(t6);

        it = times.iterator();

        while(it.hasNext()){
            Object element = it.next();
            System.out.println(element);  // Wed Jan 03 00:00:00 CST 2007... 直接输出并不能满足格式要求
            if(element instanceof Date){
                Date d = (Date)element;
                System.out.println(sdf.format(d)); // 2007-01-03...  也能按照从小到大排列
            }


        }


    }
}

package com.company.sortedSet;
/*
    前面一个java程序中,所使用的的三个类都是SUN提供的类

    如果程序员直接定义类,然后存入TreeSet中,再遍历的时候,就会包错User cannot be cast to class java.lang.Comparable

    这需要程序员在自己定义类的时候实现java.lang.Comparable接口

    【注】SortedSet集合存储元素为什么可以自动排序?
            因为被存储的元素实现了Compareable接口,SUN编写的TreeSet集合在添加元素的时候,
         会调用compareTo方法完成比较。
*/

import java.util.*;

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

        SortedSet us = new TreeSet();

        User u1 = new User("Jack", 25);
        User u2 = new User("Tom", 18);
        User u3 = new User("Tony", 23);
        User u4 = new User("Andy", 27);
        User u5 = new User("Bob", 20);

        us.add(u1);
        us.add(u2);
        us.add(u3);
        us.add(u4);
        us.add(u5);


        // 遍历
        Iterator it = us.iterator();
        while (it.hasNext()) {
            Object element = it.next();
            System.out.println(element);  // User cannot be cast to class java.lang.Comparable
        }

    }
}

class User implements Comparable {
    String name;
    int age;


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

    public String toString() {
        return "User[name = " + name + ",age = " + age + "]";
    }

    // 实现java.lang.Compareable;接口中的compareTo方法
    // 该方法程序员负责实现,SUN提供的程序已经调用了该方法

    // 需求1:按照User的age排序
    /*
    public int compareTo(Object o){
        // 编写一个比较规则
        int age1 = this.age;
        int age2 = ((User)o).age;
        return age1 - age2;  // age1-age2 从小到大排列;  age2-age1 从大到小排列
    }

    */

    // 需求2:按照User的name排序
    public int compareTo(Object o) {

        String name1 = this.name;
        String name2 = ((User) o).name;
        // 调用SUN公司在String类中写好的compareTo方法
        return name1.compareTo(name2);

    }

}

package com.company.sortedSet;
/*
    让SortedSet集合做到排序的另一种方式: java.util.Comparator;

    单独编写一个比较器

    【注】现在已经讲述了SoretedSet排序的两种实现方法:
        ①在定义类的时候实现Comparable接口,重写compareTo()方法
        ②定义普通的类,然后单独编写一个类比较器,在创建TreeSet集合的时候,需要提供一个比较器

        这两种方法有限石油第二种方法,因为它耦合度低,第一种方法定义的类必须实现Comparable接口,耦合度高。
        SUN公司TreeSet源码,也是优先调用类比较器的。

*/
import java.util.*;
public class SortedSetTest03 {
    public static void main(String[] args) {

        // 创建TreeSet集合的时候提供一个比较器
        SortedSet ps = new TreeSet(new ProductComparator());

        Product p1 = new Product(8.88);
        Product p2 = new Product(5.68);
        Product p3 = new Product(6.42);
        Product p4 = new Product(9.23);
        Product p5 = new Product(8.21);

        ps.add(p1);
        ps.add(p2);
        ps.add(p3);
        ps.add(p4);
        ps.add(p5);

        Iterator it = ps.iterator();

        while(it.hasNext()){
            System.out.println(it.next());
        }


    }
}


class Product{
    double price;

    Product(double price){
        this.price = price;
    }

    public String toString(){
        return "Product[price:" + price +"]";
    }
}

// 单独编写一个比较器
class ProductComparator implements Comparator{

    // 需求:按照商品价格排序
    public int compare(Object o1, Object o2){

        double price1 = ((Product)o1).price;
        double price2 = ((Product)o2).price;

        if(price1 == price2){
            return 0;
        }else if(price1 > price2){
            return 1;
        }else{
            return -1;
        }

    }
}

/*

// 在创建集合时,也可以采用类名内部类的方式
// 匿名内部类:不推荐使用,因为比较器无法得到重复使用。
// 这种方法需要注意在创建是内部类必须是:new Comparator(){}
SortedSet ps = new TreeSet(new Comparator(){

    public int compare(Object o1, Object o2){

        double price1 = ((Product)o1).price;
        double price2 = ((Product)o2).price;

        if(price1 == price2){
            return 0;
        }else if(price1 > price2){
            return 1;
        }else{
            return -1;
        }
    }

});

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值