为了账号安全,请及时绑定邮箱和手机立即绑定

4-Java常用工具类-集合

标签:
Java

集合: 集合的概念;体系结构;实际应用

通过案例为大家展示集合中类和接口的使用。

生活中的集合: 人或事物聚集到一起; 数学中的集合: 具有某种特性的事物的整体

Java: Java中的集合是工具类,可以存储任意数量的具有共同属性的对象。

超市购物的购物车就是容器: 存储商品的信息,数组也可以,为什么要使用集合?

疑问: 为什么使用集合,而不用数组呢?

问题: 存储20名学生的学生信息。20是不变的,就是这么多。
问题: 存储商品信息。不知道自己要买多少商品。

数组用于固定长度的数据场景,集合更适合数据动态变化的场景。

集合应用场景: 无法预测存储数据的数量;同时存储具有一对一关系的数据(商品信息&详情);需要进行数据的增删;数据重复问题

Set不允许插入重复数据。

集合框架的体系结构

Collection 类的对象 Map 键值对(键是商品的编号,值是商品的信息)

5c1348aa0001787706760327.jpg

Collection下有三个子接口。List和Queue中存放的数据要求是有序的,并且允许重复的。Set中是无序的,并且不允许重复的。

每个接口下又有实现类: ArrayList 长度动态增长的数组。 LinkedList 同时实现List接口,表示链表的内容; HashSet

Map 的实现类是HashMap,里面存储以键值对表现的形式。

5c1348aa0001133f11620487.jpg

List(列表)概述

List是元素有序并且可以重复的集合,称为序列

List可以精确的控制每个元素的插入位置,或删除某个位置的元素

List的两个主要实现类是ArrayList和LinkedList

本课程主要介绍ArrayList类,因为这个类使用比较多。ArrayList和数组是比较相似的,只是它的长度是可以动态增长的,也是在内存上一片连续的存储空间进行存储的。LinkedList本身是一个链表,这两个中方法的作用是几乎相同的。

ArrayList底层是由数组实现的;动态增长,以满足应用程序的需求; 在列表尾部插入或删除数据非常有效(中间插入删除挪位过多);更适合查找和更新元素;ArrayList中的元素可以为null

java.util 包中的,是需要我们自己导入的。

add方法,向集合中添加元素。clear方法,清空集合中元素。contains方法 判断集合中是否包含给的对象。

isEmpty 集合是否为空, iterator 集合遍历时非常常用的方法。remove方法,移除集合中的某个元素。size()集合元素个数。

List 中 get方法,返回指定index的元素。 indexOf 返回某个对象在列表中的index; sort 对列表进行排序。

ArrayList 无参构造,容量为10, 有参 通过已存在的Collection 构造ArrayList。

案例: 在List中存储并操作字符串信息。

案例:用ArrayList存儲編程語言的名称,并輸出。

名称包括 Java C C++ Go和Swift

package cn.mtianyan.set;import java.util.ArrayList;import java.util.List;public class ListDemo1 {    public static void main(String[] args) {        // 用ArrayList存储编程语言的名称,并输出
        List list=new ArrayList();
        list.add("Java");
        list.add("C");
        list.add("C++");
        list.add("Go");
        list.add("swift");        // 输出列表中元素的个数
        System.out.println("列表中元素的个数为:"+list.size());        
        // 遍历输出所有编程语言
        System.out.println("**************************************");        for(int i=0;i<list.size();i++){
            System.out.print(list.get(i)+",");
        }        
        // 移除列表中的C++
        System.out.println();        // list.remove(2);
        list.remove("C++");
        System.out.println("**************************************");
        System.out.println("移除C++以后的列表元素为:");        for(int i=0;i<list.size();i++){
            System.out.print(list.get(i)+",");
        }
    }

}

5c1348aa0001f99411720311.jpg

开辟内存空间,add()不断添加元素

5c1348ab00018e6411510294.jpg

运行结果:

5c1348ab0001849904140152.jpg

remove有两种实现,可以移除指定下标,也可以移除某个对象(如"c++")。

公告需求管理

案例: 公告管理;首页等显示公告。

需求:公告的添加和显示;在指定位置处插入公告;删除公告;修改公告

公告类属性: 编号 id;标题 title;创建人 creator;创建时间 createTime

公告类方法: 构造方法,getId方法。获取和设置属性值的方法。

案例: 公告的添加和显示

package cn.mtianyan.set;import java.util.Date;public class Notice {    private int id;             // ID
    private String title;       // 标题
    private String creator;     // 创建人
    private Date createTime;    // 创建时间
    public Notice(int id, String title, String creator, Date createTime) {        super();        this.id = id;        this.title = title;        this.creator = creator;        this.createTime = createTime;
    }    public int getId() {        return id;
    }    public void setId(int id) {        this.id = id;
    }    public String getTitle() {        return title;
    }    public void setTitle(String title) {        this.title = title;
    }    public String getCreator() {        return creator;
    }    public void setCreator(String creator) {        this.creator = creator;
    }    public Date getCreateTime() {        return createTime;
    }    public void setCreateTime(Date createTime) {        this.createTime = createTime;
    }
}

后面会学习到一种叫Bean的定义方式。

package cn.mtianyan.set;import java.util.ArrayList;import java.util.Date;public class NoticeTest {    public static void prinf(ArrayList noticeList,int i){
        System.out.printf("%-15s",(i + 1)+ ":" + ((Notice) (noticeList.get(i))).getTitle());
        System.out.printf("%-6s","\t"+((Notice)(noticeList.get(i))).getCreator());
        System.out.printf("%-20s","\t"+((Notice)noticeList.get(i)).getCreateTime());
        System.out.println();
    }    public static void main(String[] args) {        // 创建Notice类的对象,生成三条公告,new Date()当前时间
        Notice notice1 = new Notice(1, "欢迎来到简书,天涯明月笙!", "管理员", new Date());
        Notice notice2 = new Notice(2, "请同学们按时提交作业!", "老师", new Date());
        Notice notice3 = new Notice(3, "请同学们按时完成试卷!", "老师", new Date());        // 添加公告
        ArrayList noticeList = new ArrayList();
        noticeList.add(notice1);
        noticeList.add(notice2);
        noticeList.add(notice3);        // 显示公告
        System.out.println("公告的内容为:");        for (int i = 0; i < noticeList.size(); i++) {
            prinf(noticeList,i);
        }

        System.out.println("**************************************");        // 在第一条公告后面添加一条新公告
        Notice notice4 = new Notice(4, "在线编辑器可以使用啦!", "管理员", new Date());
        noticeList.add(1, notice4);        // 显示公告
        System.out.println("第一条公告后插入新公告后的内容为:");        for (int i = 0; i < noticeList.size(); i++) {
            prinf(noticeList,i);
        }

        System.out.println("**************************************");        // 删除按时提交作业的公告
        noticeList.remove(2);        // 显示公告
        System.out.println("删除第3条公告后的内容为:");        for (int i = 0; i < noticeList.size(); i++) {
            prinf(noticeList,i);
        }        
        // 将第二条公告改为:Java在线编辑器可以使用啦!
        System.out.println("**************************************");        // 修改第二条公告中title的值
        notice4.setTitle("Java在线编辑器可以使用啦!");        // noticeList.set(1, notice4);
        System.out.println("修改后公告的内容为:");        for (int i = 0; i < noticeList.size(); i++) {
            prinf(noticeList,i);
        }
    }

}

5c1348ab0001df2e06200424.jpg

注意:在本例题中,使用setTitle就可以了,如果创建了一个新的对象用新的对象去替换notice4的时候需要调用ArrayList的set方法。

总计一下上面用到的方法: add(notice1);添加对象到队尾,add(1, notice4);添加到指定下标。noticeList.remove(2);移除指定下标。
noticeList.set(1, notice4); 修改某个下标的对象。

编程练习

定义一个员工信息类Employee ,使用ArrayList对员工信息进行添加和显示。

效果图:

5c1348ac0001e1f502400129.jpg

package cn.mtianyan.set;import java.util.ArrayList;public class EmployeeTest {    public static void main(String[] args) {
        ArrayList employeeList = new ArrayList();
        Employee employee1 = new Employee("张三",5000.0);
        Employee employee2 = new Employee("李四",5500.0);
        Employee employee3 = new Employee("赵六",4000.0);
        employeeList.add(employee1);
        employeeList.add(employee2);
        employeeList.add(employee3);

        System.out.printf("%-10s","员工性别");
        System.out.printf("%-5s","员工薪资");
        System.out.println();        for (Object employee:employeeList) {
            System.out.printf("%-11s",((Employee)employee).getName());
            System.out.printf("%-5s",((Employee)employee).getSalary());
            System.out.println();
        }

    }
}

5c1348ac0001bcec03490125.jpg

Set概述

Set是元素无序并且不可以重复的集合,被称为集。实现类是HashSet

HashSet是Set的一个重要实现类,称为哈希集;HashSet中的元素无序并且不可以重复;HashSet中.只允许一个null元素;具有良好的存取和查找性能

HashSet的底层是HashMap,HashMap我们后面会讲到

Set的常用方法:

有equals方法和hashCode方法。

HashSet 有四个构造方法。加载因子。

案例:用HashSet存储多个表示颜色的英文单词,并输出。

单词包括: "blue","red","black","yellow"和"white"

package cn.mtianyan.set;import java.util.HashSet;import java.util.Iterator;import java.util.Set;public class WordDemo {    public static void main(String[] args) {        // 将英文单词添加到HashSet中
        Set set = new HashSet();        // 向集合中添加元素
        set.add("blue");
        set.add("red");
        set.add("black");
        set.add("yellow");
        set.add("white");        // 显示集合的内容
        System.out.println("集合中的元素为:");
        Iterator it = set.iterator();        // 遍历迭代器并输出元素
        while (it.hasNext()) {
            System.out.print(it.next() + "   ");
        }
        System.out.println();        // 在集合中插入一个新的单词
        // set.add("green");
        set.add("white");
        it = set.iterator();        // 遍历迭代器并输出元素
        System.out.println("**************************");
        System.out.println("插入重复元素后的输出结果为:");        while (it.hasNext()) {
            System.out.print(it.next() + "   ");
        }        // 插入失败,但是不会报错
    }

}

Iterator (迭代器): Iterator接口可以以统一的方式对各种集合元素进行遍历

hasNext()方法检测集合中是否还有下一个元素,遍历终止条件;next()方法返回集合中的下一个元素

Iterator it = set.iterator(); 将set中数据存放到迭代器中。

        while (it.hasNext()) {
            System.out.print(it.next() + "   ");
        }

以hasNext为循环终止条件,next()取出值。

set.add("green");

运行结果:

5c1348ac000164fe09220098.jpg

重复元素:插入失败,但是不会报错

宠物猫信息管理概述

演示如何在HashSet中添加自定义类的对象

需求:添加和显示宠物猫信息; 查找某只宠物猫的信息并输出;修改宠物猫的信息;删除宠物猫信息

属性: 名字name;年龄month;品种species

方法: 构造方法;获取和设置属性值的方法;其他方法

添加和显示信息

package cn.mtianyan.set;public class Cat {    private String name; //名字
    private int month; //年龄
    private String species;//品种
    
    //构造方法
    public Cat(String name, int month, String species) {        super();        this.name = name;        this.month = month;        this.species = species;
    }    //getter与setter方法
    public String getName() {        return name;
    }    public void setName(String name) {        this.name = name;
    }    public int getMonth() {        return month;
    }    public void setMonth(int month) {        this.month = month;
    }    public String getSpecies() {        return species;
    }    public void setSpecies(String species) {        this.species = species;
    }
}
package cn.mtianyan.set;import java.util.HashSet;import java.util.Iterator;import java.util.Set;public class CatTest {    public static void main(String[] args) {        // 定义宠物猫对象
        Cat huahua = new Cat("花花", 12, "英国短毛猫");
        Cat fanfan = new Cat("凡凡", 3, "中华田园猫");        // 将宠物猫对象放入HashSet中
        Set<Cat> set = new HashSet<Cat>();
        set.add(huahua);
        set.add(fanfan);        // 显示宠物猫信息
        Iterator<Cat> it = set.iterator();        while (it.hasNext()) {
            System.out.println(it.next());
        }
}
}

运行结果:

5c1348ac00016cdf06860170.jpg

可以看到这是默认的toString方法的输出。 重写toString方法

    @Override
    public String toString() {        return "[姓名:" + name + ", 年龄:" + month + ", 品种:" + species + "]";
    }

20180807154557_gTF0Kj_Screenshot.jpeg

添加重复数据

插入一个与花花一样属性的猫

        // 再添加一个与花花属性一样的猫
        Cat huahua01 = new Cat("花花", 12, "英国短毛猫");
        set.add(huahua01);
        System.out.println("**********************************");
        System.out.println("添加重复数据后的宠物猫信息:");
        it = set.iterator();        while (it.hasNext()) {
            System.out.println(it.next());
        }

运行结果:

20180807154746_oWTwZ0_Screenshot.jpeg

使用了new关键字,有两个对象指向两块不同的内存。

疑问:之前相同的字符串不允许添加到集合呀?

//  @Override//  public int hashCode() {//      final int prime = 31;//      int result = 1;//      result = prime * result + month;//      result = prime * result + ((name == null) ? 0 : name.hashCode());//      result = prime * result + ((species == null) ? 0 : species.hashCode());//      return result;//  }
    @Override
    public int hashCode() {        return Objects.hash(name, month, species);
    }

对于普通的ArrayList要找100,得遍历到100才找得到

20180807160410_YdZwDO_Screenshot.jpeg

假如这100个数据中根本没有我们要找的数据,我们也得全部遍历一遍才可以。

20180807160553_yEjDcA_Screenshot.jpeg

通过HashCode规则对于数据进行分桶处理

我们可以使用n%3的余数这个规则来放入桶中

20180807160742_oxKSRc_Screenshot.jpeg

查找时,先判断数据在哪个桶里,如果一个都不满足,那么就提示找不到。遍历桶内元素。

这里确定是在哪一个桶里使用hashCode方法,在一个确定的桶里进行遍历时使用equals方法来比较正在遍历的元素和我们要找的元素。

hashCode就使用自动生成的。

    @Override
    public boolean equals(Object obj) {        // 判断对象是否相等,相等则返回true,不用继续比较属性了
        if(this==obj)            return true;        // 判断obj是否是Cat类的对象
        if(obj.getClass()==Cat.class){
            Cat cat=(Cat)obj;            return cat.getName().equals(name)&&(cat.getMonth()==month)&&(cat.getSpecies().equals(species));
        }        return false;
    }

这里用到了一个反射,使用对象获取它所属的类,与Cat.class属性进行比较。

20180807161306_mBHFgl_Screenshot.jpeg

查找宠物猫信息

        System.out.println("**********************************");        // 重新插入一个新宠物猫
        Cat huahua02 = new Cat("花花二代", 2, "英国短毛猫");
        set.add(huahua02);
        System.out.println("添加花花二代后的宠物猫信息:");
        it = set.iterator();        while (it.hasNext()) {
            System.out.println(it.next());
        }

20180807161507_ULTH4l_Screenshot.jpeg

第一种,使用对象名查找(传入一个对象)

        System.out.println("**********************************");        // 在集合中查找花花的信息并输出
        if (set.contains(huahua)) {
            System.out.println("花花找到了!");
            System.out.println(huahua);
        } else {
            System.out.println("花花没找到!");
        }

20180807170052_KY0JOn_Screenshot.jpeg

第二种方法: 通过名字进行查找

        // 在集合中使用名字查找花花的信息
        System.out.println("**********************************");
        System.out.println("通过名字查找花花信息");        boolean flag = false;
        Cat c = null;
        it = set.iterator();        while (it.hasNext()) {
            c = it.next();            if (c.getName().equals("花花")) {
                flag = true;// 找到了
                break;
            }
        }        if (flag) {
            System.out.println("花花找到了");
            System.out.println(c);
        } else {
            System.out.println("花花没找到");
        }

编程练习

定义一个学生类,使用HashSet对学生类的对象进行管理:执行添加操作,然后解决重复数据的添加问题。

效果图:

20180807170452_toXp9r_Screenshot.jpeg

任务

  1. 定义一个学生类Student:

  • 属性为:学号stuld(int),姓名name (String),成绩score ( float )

  • 方法为: 构造方法,getter和setter方法,toString方法

  • 重写hashCode()和equals(方法,equals方法的判断依据是学号和姓名相等

定义三个Student类的对象,添加到HashSet中

显示HashSet中元素的内容

添加一个重复数据到Set中,观察输出结果

package cn.mtianyan.student;import java.util.Objects;public class Student {    private int stuId;    private String name;    private float score;    public Student(int stuId, String name, float score) {        this.stuId = stuId;        this.name = name;        this.score = score;
    }    public int getStuId() {        return stuId;
    }    public void setStuId(int stuId) {        this.stuId = stuId;
    }    public String getName() {        return name;
    }    public void setName(String name) {        this.name = name;
    }    public float getScore() {        return score;
    }    public void setScore(float score) {        this.score = score;
    }    @Override
    public String toString() {        return "[" +                "学号:" + stuId +                ", 姓名: " + name + '\'' +                ", 成绩: " + score +                ']';
    }    @Override
    public boolean equals(Object o) {        if (this == o) return true; // 直接是一个对象,必然一样。
        if (!(o instanceof Student)) return false; // 如果传入的不是学生类的对象,那么必然不是
        Student student = (Student) o; // 将Object转换为Student
        // 学号 & 姓名 是否相等
        return getStuId() == student.getStuId() &&//                Float.compare(student.getScore(), getScore()) == 0 &&
                Objects.equals(getName(), student.getName());
    }    @Override
    public int hashCode() {        return Objects.hash(getStuId(), getName());
    }
}
package cn.mtianyan.student;import java.util.HashSet;import java.util.Iterator;public class StudetTest {  
    public static void main(String[] args) {
        Student student1 = new Student(3,"William",65.0f);
        Student student2 = new Student(1,"Tom",87.0f);
        Student student3 = new Student(2,"Lucy",95.0f);


        HashSet hashSet = new HashSet();
        hashSet.add(student1);
        hashSet.add(student2);
        hashSet.add(student3);

        Iterator iterator = hashSet.iterator();        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        Student student4 = new Student(2,"Lucy",16.0f);
        hashSet.add(student4);

        System.out.println("*****************");
        Iterator iterator2 = hashSet.iterator();        while (iterator2.hasNext()){
            System.out.println(iterator2.next());
        }
    }



作者:天涯明月笙
链接:https://www.jianshu.com/p/faaf4b23ebfc


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消