Java面向对象基础3 -- 集合

1. 集合概览

1.1 Java中集合的由来

程序运行结束时我们知道程序创建多少个对象,但在在程序开发阶段,我们无法预测程序需要常见多少个对象,甚至不知道它的准确类型,就像我们没事逛超市时,根本不知道我们会买几件商品,会买哪种商品,那我们时需要对一辆购物车还是拎一个包呢?

为了满足这些编程,我们需要设计出一种可以容纳不同类型、不同数量的对象的存储结构,我们已有的数组显然是不能满足这种要求,因为数组只能存放统一类型的数据,而且其存储长度是固定的,集合随之而出。

1.2 集合与数据的区别

数组是java语言中内置的数据类型,是线性排列的,执行效率或者类型检查都是最快的,但其长度固定、不易于增删是限制其使用的主要因素。

集合与数组的主要区别如下表:

 存储对象存放内容存储长度存储方式
数组既可以存储基本数据类型,也可以存储引用数据类型,但只能存放一种类型的数据存储基本数据类型时:存放的是数值
存放引用数据类型时:存放的是地址值
有限的,在数组声明时确定顺序存储
集合只能存储引用数据类型(存放基本数据类型时被自动装箱成对象);在没有使用泛型时,可以存放多种不同类型的数据,使用泛型后只能存放一种类型存放的是地址值无限的可能是顺序的,也可能是乱

1.3 集合框架图

2. 迭代器Iterator

Iterator是Java集合的顶层接口(Map接口 是 map 系列集合的顶层接口)

Object next():返回迭代器刚越过的元素的引用,返回值是 Object,需要强制转换成自己需要的类型(),如果创建Iterator对象时使用泛型,则不用强制转换

boolean hasNext():判断容器内是否还有可供访问的元素

void remove():删除迭代器刚越过的元素

除了 map 系列的集合,我们都能通过迭代器来对集合中的元素进行遍历,代码如下。

// 构造list3的Iterator迭代器it
Iterator<Person1> it = list3.iterator();

// 通过迭代器遍历list3的元素
while(it.hasNext()) {
    System.out.println(it.next().getId()
        +","+it.next().getName());
}

3. Collection 接口

Collection是最基本的集合接口,常见的方法如下:

4. List接口

List 是有序,可以重复的集合,继承于 Collection 接口,所以基本的方法如上所示。

List 接口的两个典型实现:

① List list1 = new ArrayList(); 底层数据结构是数组,查询快,增删慢;线程不安全,效率高

② List list3 = new LinkedList(); 底层数据结构是链表,查询慢,增删快;线程不安全,效率高

3.1 ArrayList

ArrayList类实现List接口,常见的方法如下表:

ArrayList自动扩充机制

实现机制:ArrayList.ensureCapacity(int minCapacity)首先得到当前elementData属性的长度oldCapacity。然后通过判断oldCapacity和minCapacity参数谁大来决定是否需要扩容, 如果minCapacity大于 oldCapacity,那么我们就对当前的List对象进行扩容。 扩容的的策略为:取(oldCapacity * 3)/2 + 1和minCapacity之间更大的那个。然后使用数组拷 贝的方法,把以前存放的数据转移到新的数组对象中 如果minCapacity不大于oldCapacity那么就不进行扩容。

3.2 LinkedList

LinkedList实现了List接口,允许null元素。LinkenList底层采用了双向链表来存储数据,每个节点都存储着上一个节点和下一个节点的地址以及本节点的数据。常见的方法如下表:

 4. Set

Set实现接口List,是无序集合,无法使用get方法获取指定的对象,Set集合重复对象无法添加进去

4.1 HashSet

【Set hashSet = new HashSet();】

①、HashSet:不能保证元素的顺序;不可重复;不是线程安全的;集合元素可以为 NULL;

②、其底层其实是一个数组,存在的意义是加快查询速度。我们知道在一般的数组中,元素在数组中的索引位置是随机的,元素的取值和元素的位置之间不存在确定的关系,因此,在数组中查找特定的值时,需要把查找值和一系列的元素进行比较,此时的查询效率依赖于查找过程中比较的次数。而 HashSet 集合底层数组的索引和值有一个确定的关系:index=hash(value),那么只需要调用这个公式,就能快速的找到元素或者索引。

③、对于 HashSet: 如果两个对象通过 equals() 方法返回 true,这两个对象的 hashCode 值也应该相同。

 1、当向HashSet集合中存入一个元素时,HashSet会先调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据hashCode值决定该对象在HashSet中的存储位置

1.1、如果 hashCode 值不同,直接把该元素存储到 hashCode() 指定的位置

1.2、如果 hashCode 值相同,那么会继续判断该元素和集合对象的 equals() 作比较

1.2.1、hashCode 相同,equals 为 true,则视为同一个对象,不保存在 hashSet()中

1.2.2、hashCode 相同,equals 为 false,则存储在之前对象同槽位的链表上,这非常麻烦,我们应该约束这种情况,即保证:如果两个对象通过 equals() 方法返回 true,这两个对象的 hashCode 值也应该相同。

注意:每一个存储到 哈希 表中的对象,都得提供 hashCode() 和 equals() 方法的实现,用来判断是否是同一个对象对于 HashSet 集合,我们要保证如果两个对象通过 equals() 方法返回 true,这两个对象的 hashCode 值也应该相同。

【重写equals()和HashCode()方法】

Set中存放的是引用类型数据,怎么判断两个引用类型数据是否相同呢?这就需要我们重写equals() 和HashCode()方法

    @Override
	public int hashCode() {
		return 0;
	}
	// 重写equals方法
	@Override
	public boolean equals(Object obj) {
		if(this == obj) {
			return true;
		}
		if (obj instanceof Person1) {
			Person1 p = (Person1) obj;
			if( p.id != null && p.id.equals(this.id) 
					&& p.name != null && p.name.equals(this.name)) {
				return true;
			}
		}
		return false;
	}

5. Map

Map提供了一组键值的映射。其中存储的每个对象都有一个相应的关键字(key),关键字决定了对象在Map中的存储位置。关键字应该是唯一的,每个key 只能映射一个value。

因为Map 集合即没有实现于 Collection 接口,也没有实现 Iterable 接口,所以不能对 Map 集合进行 for-each 遍历。

5.1 HashMap

键值对,key不能重复,但是value可以重复;key的实现就是HashSet;value对应着放;允许null的键或值

HashMap的创建:

package com.ppw.test;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class TestMap {
	public static void main(String[] args) {
		Map <String, Object> map1 = new HashMap<String,Object>();
		map1.put("1000", "Wang1");
		map1.put("1001", "Wang2");
		map1.put("1002", "Wang3");
		System.out.println(map1.size());
		map1.remove("1000");
		System.out.println(map1.size());
		map1.put("1000", "Wang1");

		// Map对象中没有Iterator迭代器,需要由Map对象找到KeySet,找
		Iterator<String> it = map1.keySet().iterator();
		// 不是顺序选取keySet中的值,所以出来的顺序和我们添加的顺序不一样
		// 每一次调用it.next,it.next指向的地址就会发生变化
		while(it.hasNext()) {
			String str = it.next();	// 如果Iterator创建it没有添加泛型时,此句便会报错
			System.out.println(str+","+map1.get(str));
		}
	}
}

以上整理参考链接如下,如果侵权请联系删除:

https://blog.csdn.net/weixin_41719737/article/details/84108569

https://www.cnblogs.com/ysocean/p/6555373.html

https://blog.csdn.net/weixin_43088443/article/details/112971103

https://www.cnblogs.com/chenglc/p/8073049.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值