【从零开始的Java开发】1-5-4 ArrayList、HashSet、HashMap 概述与案例

集合框架的体系结构

在这里插入图片描述

List概述

  • List是元素有序并且可以重复的集合,称为序列
  • List可以精确的控制每个元素的插入位置,或删除某个位置的元素。
  • List的两个主要实现类是ArrayListLinkedList

ArrayList

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

案例:在List中操作String

  1. add
  2. size
  3. get
  4. remove

代码:

public static void main(String[] args) {
		// TODO Auto-generated method stub
		// 用ArrayList存储编程语言的名称并输出:Java、C、C++、Go

		List list = new ArrayList();
		list.add("Java");
		list.add("C");
		list.add("C++");
		list.add("Go");

		// 输出列表中元素的个数
		System.out.println(list.size());

		// 遍历输出所有编程语言
		for (int i = 0; i < list.size(); i++) {
			System.out.print(list.get(i) + " ");
		}
		System.out.println();

		// 移除列表中的C++
		list.remove(2);

		// 移除列表中的Java
		list.remove("Java");

		// 查看
		for (int i = 0; i < list.size(); i++) {
			System.out.print(list.get(i) + " ");
		}

	}

输出:

4
Java C C++ Go 
C Go 

案例:公告管理——在ArrayList中对自定义对象的操作

需求

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

即:增删查改。

公告类属性:

  • 编号 id
  • 标题 title
  • 创建人 creator
  • 创建时间 createTime

公告类方法:

  • 构造方法
  • Getter Setter

公告类:

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;
	}

}

公告测试类:

public class NoticeTest {

	public static void main(String[] args) {
		// 创建Notice类的对象,生成三条公告
		Notice not1 = new Notice(1, "欢迎学习Java!", "管理员", new Date());
		Notice not2 = new Notice(2, "请按时提交作业!", "老师", new Date());
		Notice not3 = new Notice(3, "考勤通知!", "老师", new Date());

		// 添加公告
		ArrayList noticeList = new ArrayList();
		noticeList.add(not1);
		noticeList.add(not2);
		noticeList.add(not3);

		// 显示公告
		System.out.println("公告内容为:");
		for (int i = 0; i < noticeList.size(); i++) {
			// 要强制转换:因为get(i)返回的是Object,它没有getTitle方法
			System.out.println((i + 1) + "    " + ((Notice) (noticeList.get(i))).getTitle());

		}
		System.out.println();

		// 在第一条公告后添加新公告
		Notice not4 = new Notice(4, "在线编辑器可以使用了", "管理员", new Date());
		noticeList.add(1, not4);

		// 删除按时完成作业的公告
		noticeList.remove(2);
		
		// 显示公告
		System.out.println("修改后公告内容为:");
		for (int i = 0; i < noticeList.size(); i++) {
			// 要强制转换:因为get(i)返回的是Object,它没有getTitle方法
			System.out.println((i + 1) + "    " + ((Notice) (noticeList.get(i))).getTitle());

		}
		System.out.println();
		
		//将第二条公告改为:Java在线编辑器可以使用了!
		not4.setTitle("Java在线编辑器可以使用了");

		// 显示公告
		System.out.println("修改后公告内容为:");
		for (int i = 0; i < noticeList.size(); i++) {
			// 要强制转换:因为get(i)返回的是Object,它没有getTitle方法
			System.out.println((i + 1) + "    " + ((Notice) (noticeList.get(i))).getTitle());

		}
		System.out.println();
	}

}


输出:

公告内容为:
1    欢迎学习Java!
2    请按时提交作业!
3    考勤通知!

修改后公告内容为:
1    欢迎学习Java!
2    在线编辑器可以使用了
3    考勤通知!

修改后公告内容为:
1    欢迎学习Java!
2    Java在线编辑器可以使用了
3    考勤通知!

Set概述

  • Set是元素无序且不可重复的集合,称为
  • HashSet:是Set的一个重要实现类,称为哈希集,具有良好的存取和查找性能,底层是HashMap

案例:在Set中操作String

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

关于迭代器 Iterator

  • Iterator接口可以以统一的方式对各种集合元素进行遍历
  • 有两个重要的方法:HasNext()next()
  • HasNext():检测集合中是否还有下一个元素
  • next():返回集合中的下一个元素

由样例可见:set的插入是无序的,且不可重复。

public class SetDemo1 {

	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("whilte");

		// 显示输出
		System.out.println("集合中的元素为:");
		Iterator it = set.iterator();
		while (it.hasNext()) {
			System.out.print(it.next() + " ");
		}
		System.out.println();

		// 在集合中插入新的单词
		set.add("green");

		// 再显示输出
		System.out.println("插入元素后集合中的元素为:");
		it = set.iterator();
		while (it.hasNext()) {
			System.out.print(it.next() + " ");
		}
		System.out.println();

		// 重复插入
		set.add("green");
		// 再显示输出
		System.out.println("插入重复元素后的集合中的元素为:");
		it = set.iterator();
		while (it.hasNext()) {
			System.out.print(it.next() + " ");
		}

		// 插入失败,但是不会报错

	}

}

输出:

集合中的元素为:
red blue black yellow whilte 
插入元素后集合中的元素为:
red green blue black yellow whilte 
插入重复元素后的集合中的元素为:
red green blue black yellow whilte 

案例:宠物猫信息管理——在HashSet中对自定义对象的操作

需求:

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

即:增删查改。

宠物猫属性:

  • 名字 name
  • 年龄 month
  • 品种 species

宠物猫方法:

  • 构造方法
  • Getter Setter 方法
  • 其他方法

重写toStringhashCodeequals方法可以这样:
在这里插入图片描述

没有重写hashCodeequals方法的情况:

宠物猫类:

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;
	}

	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;
	}

	// 重写toString方法
	@Override
	public String toString() {
		return "[姓名=" + name + ", 年龄=" + month + ", 品种=" + species + "]";
	}


}

测试类:

public class CatTest {

	public static void main(String[] args) {
		// 定义宠物猫对象
		Cat cat1 = new Cat("花花", 1, "狸花");
		Cat cat2 = new Cat("草草", 2, "英短");

		// 将宠物猫对象放到HashSet中
		Set set = new HashSet();
		set.add(cat1);
		set.add(cat2);

		// 显示
		System.out.println("显示输出:");
		Iterator it = set.iterator();
		while (it.hasNext()) {
			System.out.println(((Cat) (it.next())).toString());
		}
		System.out.println();

		// 添加重复数据
		Cat cat3 = new Cat("花花", 1, "狸花");
		set.add(cat3);

		// 显示
		System.out.println("插入重复的猫后显示输出:");
		it = set.iterator();
		while (it.hasNext()) {
			System.out.println(((Cat) (it.next())).toString());
		}
		System.out.println();
		
		//发现插入成功
	}

}

输出:插入成功

显示输出:
[姓名=花花, 年龄=1, 品种=狸花]
[姓名=草草, 年龄=2, 品种=英短]

插入重复的猫后显示输出:
[姓名=花花, 年龄=1, 品种=狸花]
[姓名=花花, 年龄=1, 品种=狸花]
[姓名=草草, 年龄=2, 品种=英短]

重写了hashCodeequals方法的情况:

// 重写HashCode
	@Override
	public int hashCode() {
		return Objects.hash(month, name, species);
	}

// 重写equals
	@Override
	public boolean equals(Object obj) {
		// 对象相等返回true
		if (this == obj)
			return true;

		// 比较内容
		if (obj.getClass() == Cat.class) {
			Cat cat = (Cat) obj;
			return cat.getName().equals(name) && cat.getMonth() == month && cat.getSpecies().equals(species);
		}

		return false;
	}

测试输出:插入失败

显示输出:
[姓名=花花, 年龄=1, 品种=狸花]
[姓名=草草, 年龄=2, 品种=英短]

插入重复的猫后显示输出:
[姓名=花花, 年龄=1, 品种=狸花]
[姓名=草草, 年龄=2, 品种=英短]

显然,重写后的才符合HashSet的要求。


测试类添加代码如下:

// 在集合中查找草草的信息并输出
		// 通过对象查找
		if (set.contains(cat2)) {
			System.out.println("草草找到了!");
			System.out.println(cat2);
		} else {
			System.out.println("草草没找到!");
		}

		// 通过名字查找
		it = set.iterator();
		boolean flag = false;
		Cat temp;
		while (it.hasNext()) {
			temp = (Cat) (it.next());
			if (temp.getName().equals("草草")) {
				System.out.println("草草找到了!");
				System.out.println(temp);
				flag = true;
				break;
			}
		}
		if (flag == false) {
			System.out.println("草草没找到!");
		}
	}

输出:

草草找到了!
[姓名=草草, 年龄=2, 品种=英短]
草草找到了!
[姓名=草草, 年龄=2, 品种=英短]


看这一句代码:temp = (Cat) (it.next());
由于next方法取出的是Object类型,而我们需要的是Cat类型——我们就要进行强制转换,这里由于我们知道其实这个temp是Cat类型的所以可以强制转换。但如果不是,就会报错。如,我们把代码改成:String temp = (String) (it.next());,则会:
在这里插入图片描述
这是一种隐患:编译时不会报错,运行时才会。
解决方法:泛型

把代码改成:

Set<Cat> set = new HashSet<Cat>();
...
Iterator<Cat> it = set.iterator();
...
temp = it.next();//这里不用强制类型转换了

这样,如果出现String temp = (String) (it.next());的代码,就会报错。

删除代码:使用增强型for循环

// 删除草草2的信息并输出
// for (Cat cat : set) 增强型for循环
for (Cat cat : set) {
	if ("草草2".equals(cat.getName())) {
		set.remove(cat);
		break;//注意,这里只有一个满足条件的猫
	}
}

// 输出查看
System.out.println("删除后的信息输出:");
for (Cat cat : set) {
	System.out.println(cat);
}

输出:

删除后的信息输出:
[姓名=花花, 年龄=1, 品种=狸花]
[姓名=草草, 年龄=2, 品种=英短]

删除成功!

删除集合所有猫的方法:removeAll()
判断集合是否为空的方法:isEmpty()
如果有多种满足删除要求的猫,我们可以这样:new一个新的set1,把满足要求的猫add进去,然后set.removeAll(set1)即可。

Map概述

  • Map中的数据是以键值对key-value的形式存储的
  • key-valueEntry类型的对象实例存在
  • 可以通过key值快速查找value
  • 一个映射不能包含重复的键:key唯一
  • 每个键只能映射到一个值

HashMap

  • 基于哈希表的Map接口的实现
  • 允许使用null值和null
  • HashMap中的Entry对象是无序排列的

在这里插入图片描述

Map接口的常用方法:(详情请见文档,这里只是大致提一下)

  • clear:清空
  • entrySet:返回键值对的所有信息
  • get:通过key取得对应value
  • keySet:取出所有key的值
  • put:相当于set的add
  • remove:移除参数为key的值
  • values:返回值

HashMap类的构造方法:
在这里插入图片描述
HashMap类的常用方法:

  • clear
  • entrySet
  • get
  • isEmpty
  • keySet
  • put
  • remove
  • size
  • values

案例:在Map中操作String

需求:完成一个类似字典的功能

  • 将单词以及单词的注释存储到HashMap中
  • 显示HashMap的内容
  • 查找某单词的注释并显示

添加和显示

输入为:

dog
狗
cat
猫
bird
鸟

代码:

public class DicDemo {

	public static void main(String[] args) {
		Map<String, String> animal = new HashMap<String, String>();

		// 存储
		/*
		 * dog-狗 cat-猫 bird-鸟
		 */
		System.out.println("请输入三组单词的注释,并存放到HashMap中");
		Scanner console = new Scanner(System.in);
		for (int i = 0; i < 3; i++) {
			String key = console.next();
			String value = console.next();
			animal.put(key, value);
		}

		// 显示value的值:无序,因此输出顺序与输入顺序不一致
		System.out.println("显示value的内容");
		Iterator<String> it = animal.values().iterator();
		while (it.hasNext()) {
			System.out.print(it.next() + "   ");
		}
		System.out.println();

		// 显示key和value的值
		Set<Entry<String, String>> entrySet = animal.entrySet();
		for (Entry<String, String> e : entrySet) {
			System.out.println(e.getKey() + "——" + e.getValue());

		}

	}

}

输出:

显示value的内容
猫   鸟   狗   
cat——猫
bird——鸟
dog——狗

查找
代码:

// 通过单词找到注释并输出:KeySet
String strSearch = console.next();
// 1.取得keySet
Set<String> ks = animal.keySet();
// 2.遍历ks
for (String key : ks) {
	if (key.equals(strSearch)) {
		System.out.println("找到啦:" + animal.get(key));
		break;
	}
}

输入:dog
输出:找到啦:狗

案例:商品信息管理

需求:使用HashMap对商品信息进行管理

  • key是商品编号,value是商品对象
  • 对HashMap中的商品进行增删查改

商品类:

属性:

  • 商品编号:id
  • 商品名称:name
  • 商品价格:price

方法:

  • 构造方法
  • Getter Setter
  • 其他方法

商品Goods类:

public class Goods {
	private String id;
	private String name;
	private double price;

	public Goods(String id, String name, double price) {
		super();
		this.id = id;
		this.name = name;
		this.price = price;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	@Override
	public String toString() {
		return "[商品编号=" + id + ", 商品名字=" + name + ", 商品价格=" + price + "]";
	}

}

测试类:

public class GoodsTest {
	public static void main(String[] args) {
		Scanner console = new Scanner(System.in);

		// 定义HashMap对象
		Map<String, Goods> goodsMap = new HashMap<String, Goods>();

		System.out.println("请输入三条商品信息:");
		for (int i = 0; i < 3; i++) {
			System.out.println("请输入商品编号:");
			String id = console.next();
			while (goodsMap.containsKey(id)) {
				System.out.println("该商品编号已经存在,请重新输入!");
				id = console.next();
			}

			System.out.println("请输入商品名字:");
			String name = console.next();
			System.out.println("请输入商品价格:");
			double price = console.nextDouble();
			Goods goods = new Goods(id, name, price);
			goodsMap.put(id, goods);
		}

		// 遍历Map
		System.out.println("显示商品信息:");
		Iterator<Goods> it = goodsMap.values().iterator();
		while (it.hasNext()) {
			System.out.println(it.next().toString());
		}
		System.out.println();
	}
}

输入:

s01
冰箱
5000
s02
手机
2000
s03
电脑
5000

输出:

显示商品信息:
[商品编号=s02, 商品名字=手机, 商品价格=2000.0]
[商品编号=s01, 商品名字=冰箱, 商品价格=5000.0]
[商品编号=s03, 商品名字=电脑, 商品价格=5000.0]

总结

在这里插入图片描述

ArrayList

  • 底层由数组实现
  • 元素有序且重复
  • 可以动态增长,以满足应用程序的需求
  • 元素值可以为null

HashSet

  • 元素无序且不可重复
  • 只允许一个null元素

HashMap

  • 键不能重复
  • 允许使用null值和null
  • HashMap中的Entry对象是无序排列的

Iterator迭代器

Iterator接口以统一的方式对各种集合元素进行遍历。

Iterator<String> it = set.iterator();
while (it.hasNext()) {
	System.out.println(it.next().toString());
}

hashCode

public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		result = prime * result + ((species == null) ? 0 : species.hashCode());
		return result;
	}

equals

// 重写equals
	@Override
	public boolean equals(Object obj) {
		// 对象相等返回true
		if (this == obj)
			return true;

		// 比较内容
		if (obj.getClass() == Cat.class) {
			Cat cat = (Cat) obj;
			return cat.getName().equals(name) && cat.getMonth() == month && cat.getSpecies().equals(species);
		}

		return false;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

karshey

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值