Java中的Set和Map集合
<!--more-->
###Set Set作为Collection的子体系,有一些特点:
- Set是无序的,存储和读取的顺序有可能不一样
- 不允许重复,要求每个元素是唯一的
- 无序所以没有索引
其中Set中的add()
方法,在添加的时候,先比较元素的哈希值,如果和已有的元素相同则不添加,如果哈希值不一样,则再进行比较==
或者equals()
方法来进行比较,如果有一个为true即重复,则也不添加。
HashSet存储自定义类型数据并实现去重
package SetAndMapDemo;
import java.util.HashSet;
public class HashSetDemo1 {
public static void main(String[] args) {
// 有自定义的Stu类
Stu s1 = new Stu("Yang", 23);
Stu s2 = new Stu("DeeJay", 22);
Stu s3 = new Stu("DeeJay", 22);
// 创建HashSet对象
HashSet<Stu> hs = new HashSet<Stu>();
hs.add(s1);
hs.add(s2);
hs.add(s3);
System.out.println(hs); // [Stu [name=DeeJay, age=22], Stu [name=DeeJay, age=22], Stu [name=Yang, age=23]]
// 可以看到s2和s3是重复的,但是也被加进了HashSet中
// 造成这种情况的原因是因为Set中add()方法的特殊性
}
}
class Stu {
String name;
int age;
public Stu(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Stu [name=" + name + ", age=" + age + "]";
}
}
出现这种情况的原因是add()方法的特殊性:
其中Set中的add()
方法,在添加的时候,先比较元素的哈希值,如果和已有的元素相同则不添加,如果哈希值不一样,则再进行比较==
或者equals()
方法来进行比较,如果有一个为true即重复,则也不添加。
如果要避免这种情况,需要重写一下equals方法:
package SetAndMapDemo;
import java.util.HashSet;
public class HashSetDemo1 {
public static void main(String[] args) {
// 有自定义的Stu类
Stu s1 = new Stu("Yang", 23);
Stu s2 = new Stu("DeeJay", 22);
Stu s3 = new Stu("DeeJay", 22);
// 创建HashSet对象
HashSet<Stu> hs = new HashSet<Stu>();
hs.add(s1);
hs.add(s2);
hs.add(s3);
System.out.println(hs); // [Stu [name=DeeJay, age=22], Stu [name=DeeJay, age=22], Stu [name=Yang, age=23]]
// 可以看到s2和s3是重复的,但是也被加进了HashSet中
// 造成这种情况的原因是因为Set中add()方法的特殊性
}
}
class Stu {
String name;
int age;
public Stu(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Stu [name=" + name + ", age=" + age + "]";
}
@Override
public boolean equals(Object obj) {
Stu other = (Stu)obj; // 先做类型转换 否则拿不到子类型的对象的成员
if(other.name.equals(this.name) && other.age == this.age) {
return true;
}else {
return false;
}
}
}
重写了equals方法之后,还是可以重复添加,这是因为add()方法在进行添加时,是先进行hashCode的比较,如果hash值一样就不会进行equals的比较。
所以一般有约定:重写了equals(),一定也要重写相应的hashCode()!!!
所以我们还需要重写hashCode():
package SetAndMapDemo;
import java.util.HashSet;
public class HashSetDemo1 {
public static void main(String[] args) {
// 有自定义的Stu类
Stu s1 = new Stu("Yang", 23);
Stu s2 = new Stu("DeeJay", 22);
Stu s3 = new Stu("DeeJay", 22);
// 创建HashSet对象
HashSet<Stu> hs = new HashSet<Stu>();
hs.add(s1);
hs.add(s2);
hs.add(s3);
System.out.println(hs); // [Stu [name=Yang, age=23], Stu [name=DeeJay, age=22]]
// 重写了equals() 和 hashCode() 之后 做到了自定义类的不重复添加
}
}
class Stu {
String name;
int age;
public Stu(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Stu [name=" + name + ", age=" + age + "]";
}
@Override
public boolean equals(Object obj) {
Stu other = (Stu)obj; // 先做类型转换 否则拿不到子类型的对象的成员
if(other.name.equals(this.name) && other.age == this.age) {
return true;
}else {
return false;
}
}
@Override
public int hashCode() {
return -1; // 直接给所有的元素都返回-1的hash值
}
}
关于上例重写hashCode()和equals()的优化
上述例子中重写equals()和hashCode()值只是做一个实例,可以进一步优化重写的方法
hashCode():
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
equals():
@Override
public boolean equals(Object obj) {
// 判断是否同一元素
if (this == obj)
return true;
// 判断是否为null
if (obj == null)
return false;
// 判断运行时类是否一直
if (getClass() != obj.getClass())
return false;
Stu other = (Stu) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null) // name为String,是引用类型,有可能为null
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
Collections 工具类
先来看Collection和Collections的区别:
Collection是集合体系的最顶层,包含了所有集合的共性.Interface Collection<E> Collections则是个工具类.Class Collections
Collections工具类的方法,就是为了操作Colleciton.
static int binarySearch(List list, T key)
二分查找
static void copy(List dest, List src)
把源列表中的数据覆盖到目标列表,注意目标列表dest的长度要大于等于源列表的长度
static void fill(List list, Object obj)
使用制定的元素填充制定的列表
static void reverse(List list)
static void shuffle(List list)
随机置换
static void sort(List<T> list)
按照列表中元素的自然顺序进行按升序进行排序
static void sort(List<T> list, Comparator<? super T> c)
static void swap(List list, int i, int j)
指定索引的元素进行互换
code
Map
java.util.Map
接口Map结构用来存储键值对
Map和Collection的区别:
- Map不是Collection的子结构
- Map是一个双列集合,常用处理有对应关系的数据
- Collection是一个单列集合,下面有不同的子体系,有的有索引有的没索引,有的允许重复有的不允许重复
####Map的常用功能
int size()
void clear()
boolean isEmpty()
V remove(Object key)
boolean containsKey(Object key)
boolean containsValue(Object value)
Set<Map.Entry<K,V>> entrySet()
V get(Object key)
Set<K> keySet()
V put(K key, V value)
Collection<V> values()
code
put 添加及修改 返回值为null和value
code
Set<K> keySet()
Collection<V> values()
code
遍历Map
1.获取所有的Key,遍历获得所有的values, keySet() values()
2.Set<Map.Entry<K,V>> entrySet()
使用HashMap存储数据并进行遍历
- 第一种情况,String作为Key:
code
- 第二种情况,自定义类型作为Key:
code 类的定义
code
自定义相同成员的类添加时可以重复添加