Set集合Map集合以及Map的三种迭代



一:Set集合:
(一):Set集合:
1、Set集合用于存储不重复的对象集合,在Set集合中存储的对象中不存在两个对象equals比较为true。
2、HashSet和TreeSet是set集合的两个常见的实现类,分别用hash表和排序二叉数的方法实现了Set集合。
(二):Set集合的遍历
1、Set集合不同于List集合,其中的元素不能和顺序的下标对应,无法从Set集合中取出特定的元素;如果希望遍历Set集合中的元素只能调用其iterator方法,通过返回的Iterator对象来完成。
HashSet和HashCode方法的关系
  1、HashSet是Set接口的实现类,通过hash表的方式实现;在将对象加入HashSet集合中时,需要获取对象的hashCode值通过hash算法索引到对应的存储空间。
首先取出对象的hashCode值   ---进行hash运算确定存储空间。
当通过contains方法判断Set集合中是否包含某个对象时,需要首先根据该对象的hashCode值索引到特定的空间,然后再和空间中的对象调用equls方法进行比较。这种查找的方法会比较效率高;
  2、hashCode方法。
1、对于重写了equals方法的对象,一般要妥善的重写继承自Object类的hashCode方法(Object提供的hashCode方法将返回该对象所在内存地址的整数形式)。
2、重写hashCode方法需要注意亮点:其一,与equals方法的一至性,即equals比较放回true的两个对象其hashCode方法返回值也应该相同;其二、hashCode返回的数值应符合hash算法的要求、(一般不要使用工具自动生成的hashCode的算法)
例如:
public class Point {
private int x;
private int y;
@Override
public boolean equals(Object obj) {
if(obj instanceof Point){
Point p = (Point)obj;
return x == p.x&&y==p.y;
}
return false;
}
@Override
public int hashCode() {
final int prime = 31;
int result =1;
result = prime*result+x;
result = prime*result+y;
return result;
}
public Point(int x,int y){
this.x=x;
this.y = y;
}
public static void main(String[] args){
Set<Point> set = new HashSet<Point>();
set.add(new Point(1,2));
set.add(new Point(3,4));
//判断是否包含制定的对象
System.out.println(set.contains(new Point(1,2)));
}
在这里的话contains是用来判断set里面是否包含指定的对象,如果不从写hashCode方法,在这里连执行equals的机会都没有,因为默认的hashCode返回的是一个内存值;
二:Map集合
1、Map接口定义的集合又称为查找表,用于存储所谓“key-Value”映射对,Key可以看成是Value的索引,作为Key的对象在集合中不可以重复。
2、根据内部数据结构的不同,Map接口有很多的实现类,其中常用的内部为hash表实现的HashMap和内部为排序二叉树实现的TreeMap。Map接口中最常用的方法为get和put。
3、
其中的put方法:将Key-Value对存入map,如果在集合中已经包含该Key,则操作将替换该Key所对应的value,返回值为该Key原来所对应的Value(如果没有则返回null)。
其中的get方法:返回与参数所对应的value对象,如果不存在则返回null;
containsKey(O o)判断集合中是否包含指定的Key
containsValue(V v)判断集合中是否包含指定的Value
(一):HashMap基本原理
数组的特点是:寻址容易,插入和删除难;而链表的特点是寻址困难,插入和删除容易。那么我们能不能作出综合两种特性的综合算法,那就是哈希表。哈希表有多种不同的实现方法, 最常用的方法--拉链法:
hashMap是由一个长度为16个元素的数组和链表组成,一个长度为16个元素的数组中,每个元素存储的是一个链表的头节点。那么这些元素是按照什么规则存储到数组中的呢。一般情况下是通过hash(key)%lengeth获得。也就是该元素的key的哈希值对数组长度取余得到。
一个线性数组是怎么随机存取的呢,在这里是这样的:
HashMap里面有一个静态内部类:Entry,其中有几个重要的属性Key ,value ,next,从属性key,value我们就能明显看出来Entry就是HashMap键值对实现的一个基础的Bean。map里面的内容都是方法Entry[]里面的
(二):HashMap的存取实现
实现代码:
存储时:
int hash = key.hashCode();
int index = hash%Entry[].length;
Entry[index] = value;
取值时:
int  hash = key.hashCode();
int index=hash%Entry[].length;
return Entry[index];
疑问:如果两个key有相同的hash值会不会覆盖
(三):hashMap的应用
Map集合是面向查询优化的数据结构,在大数据量情况下有着优良的查询性能。经常用于通过key来检索value的业务场景;
(四):hashMap性能调优
Capacity:容量,hash表里bucket(桶)的数量,也就是散列数组的大小
Initial capacity:初始容量,创建hash表的时候,初始bucket的数量,默认构建容量为16.也可一制定特定的容量。
Size:大小,当前散列表中存储数据的数量。
Load factor:加载因子,默认是0.75(75%),当向散列表中增加数据时如果size/capacity的值大于Load factor则发生扩容并且重新散列(rehash)。
性能优化,加载因子较小的时候散列查找性能会提高,同时也会浪费散列桶的容量。0.75是性能和空间相对平衡结果,在创建散列表时制定合理容量,减少rehash提高性能;
(五):map集合的遍历:
有三种方法
例如:
定义一个类来定义数据:
public class Student{
private int age ;
private String id;
private String name; 
public Student(int age,String id,String name){
this.age = age;this.name= name;this.id=id;

public String toString(){
return new StringBuilder().append(id).append(" ").append(name).append(" ").append(age).toString();
}
}
定义一个用来迭代的类:
public class StuMapTest{
public static void main(String[] args){
Map<String,Student> students = new HashMap<String,Student>();
Student st1 = new Student(25,"001","张三");
Student st2 = new Student(26,"002","李四");
Student st3 = new Student(27,"003","王五");
students.put("1001",st1);
students.put("1002",st2);
students.put("1003",st3);
}
//entrySet方法遍历
public static void entrySet(Map<String,Studnt> map){
Set<Map.Entry<String,Student>> set = map.entrySet();
for(Iterator<Map.Entry<String,Student>> i= set.iterator();i.hasNext();){
System.out.println(i.next().getValue());
}
}
//values方法遍历
public static void byValues(Map<String,Student> map){
Collection c = map.values();
for(Iterator<Student> i = c.iterator();i.hasNext();){
System.out.println(i.next());
}
}
//keySet遍历
public static void keySet(Map<String,Student> map){
Set<String> set = map.keySet();
for(Iterator<String> i = set.iterator();i.hasNext();){
System.out.println(map.get(i.next()));
}
}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值