Collection
增强for循环
实质上是利用了迭代器
int[] arr = {1, 3, 4, 5, 2};
for (int i : arr) {
System.out.println(i);
}
String[] arrs = {"JYQ","WST","WYX"};
for(String s : arrs){
System.out.println(s);
}
List<String> list = new ArrayList<>();
list.add("JYQ");
list.add("WST");
list.add("WYX");
//实质上是Iterator迭代器,故add时会出现并发修改异常
// for(String sl : list){
// if(sl.equals("JYQ")){
// list.add("WYT");
// }
// }
List数据结构
ArrayList:底层数据结构是数组,查询快,增删慢
LinkedList:底层数据结构是链表,查询慢,增删快
LinkedList
Set
不包含重复元素,没有带索引的方法,所以不能使用普通for循环遍历
HashSet
HashSet集合底层数据结构是哈希表
//HashSet对集合的迭代顺序不做任何保证
Set<String> set = new HashSet<>();
set.add("WST");
set.add("JYQ");
set.add("WYX");
set.add("WST");
for(String s : set){
System.out.println(s);
}
结果:
JYQ
WYX
WST
哈希值:是JDK根据对象的地址或字符串或数字算出来的int类型的数值
HashSet集合保证元素唯一性源码分析
HashSet<String> set = new HashSet<>();
set.add("WST");
set.add("JYQ");
set.add("WYX");
set.add("WST");
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
//hash值和元素的hashCode()方法相关
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
//如果哈希表未初始化,就对其进行初始化
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
//根据对象的哈希值计算对象的存储位置,如果该位置没有元素,就存储该元素
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
/*
存入的元素和以前的元素比较哈希值
如果哈希值不同,会继续向下执行把元素添加到集合
如果哈希值相同,会调用对象的equals()方法比较
如果返回false,会继续向下执行把元素添加到集合
如果返回true,说明元素重复,不存储
*/
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
哈希表
LinkedHashSet
TreeSet集合
TreeSet():根据其元素的自然顺序进行排序
TreeSet(Comparator comparator):根据指定的比较器进行排序
没有带索引,不能使用普通for循环遍历
自然排序Comparable的使用
Student类
package com.Set;
public class Student implements Comparable<Student>{
public String name;
public int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int compareTo(Student o) {
// return 1;//返回1按升序,返回-1按降序,0表示不添加该元素
int num = this.age - o.age;
//年龄相同,按姓名字母顺序来排序
int num2 = num == 0 ? this.name.compareTo(o.name) : num;
//字符串可以直接调用comparaTo方法是因为String重写了compareTo方法
return num2;
}
}
实现:
TreeSet<Student> ts = new TreeSet<>();
Student s1 = new Student("JYQ",23);
Student s2 = new Student("WST",24);
Student s3 = new Student("HBB",24);
Student s4 = new Student("WYX",0);
Student s5 = new Student("WYX",0);
ts.add(s1);//添加的应该为Student对象
//ClassCastException,直接添加会报错,因为未实现comparable接口
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
for (Student s : ts){
System.out.println(s.getName()+","+s.getAge()) ;
结果:
WYX,0
JYQ,23
HBB,24
WST,24
Comparator比较器
comparator比较器无需去重写类,可直接利用比较器来实现
/**
* 想用Comparator比较器理应给TreeSet传入一个实现了Comparator接口的类
* 故此方法比较麻烦,需要修改类
* 也可以用简便方法匿名内部类来实现
*/
TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int num = s1.getAge() - s2.getAge();//不能直接访问私有成员,可以通过公共方法来实现
int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
return num2;
}
});
Student s1 = new Student("JYQ", 23);
Student s2 = new Student("WST", 24);
Student s3 = new Student("HBB", 24);
Student s4 = new Student("WYX", 0);
Student s5 = new Student("WYX", 0);
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
for(Student s : ts){
System.out.println(s.getName()+","+s.getAge());
}
不重复随机数
HashSet不会自动排序,根据哈希值来存放
TreeSet:会自动排序