1、Set接口
Set 接口继承 Collection 接口,而且它不允许集合中存在重复项,每个具体的 Set 实现类依赖添加的对象的equals()方法来检查独一性。Set接口没有引入新方法,所以Set就是一个Collection,只不过其行为不同。
简洁的说:Set集合的特点为无序并且不能重复。即无序性和唯一性。
其中: HashSet底层的数据结构是哈希表
TreeSet底层的数据结构是二叉树
public class HashSetDemo {
public static void main(String[] args) {
Set<String> hashSet = new HashSet<String>();
System.out.println(hashSet.add("java1"));
System.out.println(hashSet.add("java2"));
System.out.println(hashSet.add("java3"));
System.out.println(hashSet.add("java1"));
System.out.println("最后结果:");
System.out.println(hashSet);
}
}
输出结果:
public class Student {
private String name;// 名字
private int score;// 分数
public Student(String name, int score) {
this.name = name;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public String toString() {
return "Student [name=" + name + ", score=" + score + "]";
}
}
向HashSet集合添加元素:
public class HashSetDemo2 {
public static void main(String[] args) {
Set<Student> hashSet = new HashSet<Student>();
hashSet.add(new Student("lisi", 20));
hashSet.add(new Student("wangwu", 25));
hashSet.add(new Student("lisi", 20));
hashSet.add(new Student("xss", 24));
Iterator<Student> it = hashSet.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
输出结果:
[2]为Student类 重写equals()方法 判定两个对象的内容是否一致
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (score != other.score)
return false;
return true;
}
注意:重写equals方法时public boolean equals(Object obj) 中括号内只能为Object obj,不能为自定义对象,否则不能对equals进行重写。
输出结果:
@Override
public int hashCode() {
return 11;
}
输出结果:
注意:之前我一直疑惑的一个地方,先上代码:
public static void main(String[] args) {
Set<String> hashSet = new HashSet<String>();
hashSet.add(new String("lisi"));
hashSet.add(new String("wangwu"));
hashSet.add(new String("lisi"));
hashSet.add(new String("xss"));
Iterator<String> it = hashSet.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
输出结果:
lisi
xss
public int hashCode() {
int h = hash;
if (h == 0) {
int off = offset;
char val[] = value;
int len = count;
for (int i = 0; i < len; i++) {
h = 31*h + val[off++];
}
hash = h;
}
return h;
}
其中h = 31*h + val[off++]可以看出,它们比较不是地址值,两者的值是相等的,会得到一样的结果,因此哈希值也就相同了。有时在实现Comparator接口时,并没有实现equals方法,可程序并没有报错,原因是实现该接口的类也是Object类的子类,而Object类已经实现了equals方法。
public class Student implements Comparable<Student> {
private String name;// 名字
private int score;// 分数
public Student(String name, int score) {
this.name = name;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public String toString() {
return "Student [name=" + name + ", score=" + score + "]";
}
@Override
public int compareTo(Student o) {
// TODO Auto-generated method stub
if (this.score > o.score)
return 1;
else if (this.score == o.score)
return this.name.compareTo(o.name);
return -1;
}
}
public class TreeSetDemo {
public static void main(String[] args) {
Set<Student> set = new TreeSet<Student>();
set.add(new Student("lisi", 80));
set.add(new Student("lisi33", 68));
set.add(new Student("wangwu", 95));
Iterator<Student> it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
输出结果:
Student [name=lisi, score=80]
Student [name=wangwu, score=95]
(2) 实现Comparator接口
public class TreeSetDemo {
public static void main(String[] args) {
Set<Student> set = new TreeSet<Student>(new MyComparator());
set.add(new Student("lisi", 80));
set.add(new Student("lisi33", 68));
set.add(new Student("wangwu", 80));
Iterator<Student> it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
class MyComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
// TODO Auto-generated method stub
if (o1.getScore() > o2.getScore())
return 1;
else if (o1.getScore() == o2.getScore())
return o1.getName().compareTo(o2.getName());
return -1;
}
}
相同点:
1、二者都可以实现对象的排序,不论用Arrays的方法还是用Collections的sort()方法。
不同点:
1、实现Comparable接口的类,似乎是预先知道该类将要进行排序,需要排序的类实现Comparable接口,是一种“静态绑定排序”。
2、实现Comparator的类不需要,设计者无需事先为需要排序的类实现任何接口。
3、Comparator接口里有两个抽象方法compare()和equals(),而Comparable接口里只有一个方法:compareTo()。
4、Comparator接口无需改变排序类的内部,也就是说实现算法和数据分离,是一个良好的设计,是一种“动态绑定排序”。
5、Comparator接口可以使用多种排序标准,比如升序、降序等。
1、Map接口
Map接口不是Collection接口的继承。Map接口用于维护键/值对(key/value pairs)。该接口描述了从不重复的键到值的映射。
HashMap和HashTable和底层的数据结构是哈希表
其中:HashMap线程不同步,效率高,不安全;可以存入null的key和null的value
HashTable线程同步,效率低,安全;不可以存入null的key和null的value
TreeMap底层的数据结构是二叉树(可对map中的key进行排序,跟TreeSet类似)
(1)HashMap
HashMap添加数据:
public class HashMapDemo {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
System.out.println(map.put("01", "lisi"));
System.out.println(map.put("01", "lisi2"));
System.out.println(map.put("02", "wangwu"));
System.out.println(map.put("02", "wangwu2"));
System.out.println(map.put("03", "xss"));
System.out.println(map);
}
}
输出结果:
(2)获取Map中的key_value方式
List,Set通过迭代器对元素进行遍历,而Map本身没有迭代器。它是通过将Map集合转换成Set集合,通过Set的Iterator对Set进行迭代,从而获取key和value。
【1】通过KeySet获取
Map<String, String> map = new HashMap<String, String>();
map.put("01", "lisi");
map.put("02", "wangwu");
map.put("03", "xss");
Iterator<String> it = map.keySet().iterator();
while (it.hasNext()) {
String key = it.next();
System.out.println(key + "..." + map.get(key));
}
【2】通过
entrySet获取
Map<String, String> map = new HashMap<String, String>();
map.put("01", "lisi");
map.put("02", "wangwu");
map.put("03", "xss");
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
System.out.println(entry.getKey() + "..." + entry.getValue());
}
其中keySet()方法返回值是Map中key值的集合;entrySet()的返回值也是返回一个Set集合,此集合的类型为Map.Entry。
Map.Entry是Map声明的一个内部接口,此接口为泛型,定义为Entry<K,V>。它表示Map中的一个实体(一个key-value对)。接口中有getKey(),getValue方法。
打个比方说明keySet()与entrySet()的区别:有很多对夫妻。一种方式是先取得(遍历得到)所有丈夫,然后便知道了所有妻子。一种方式就是直接取得(遍历得到)所有的结婚证。直接读结婚证夫是谁,妻是谁。