一、Set集合
- Set集合是单列集合Collection的子类,其无序,没有索引,存取顺序不一样,唯一且不重复,其实现类有HashSet、TreeSet、LinkedHashSet。
- 常有方法:继承Collection的方法,无独有方法
- 遍历方式:继承Collection的遍历方式,无独有的遍历方式
- 使用增强for
- 使用迭代器
- 调用toArray()方法,再遍历数组
二、HashSet
- set接口的具体实现类,以hash表进行存储,底层(构造方法new了hashMap())使用了HashMap,线程不安全,默认容量为16
- hashCode的值
- hashCode值是根据内存地址生成的一个十进制的整数,hashCode的方法可以重写,因此不能根据hashCode的值表示内存地址
- hashCode方法源至Object类
- hashCode值不能判断是否是同一对象,应为引用类型一般会重写hashCode方法
- String重写了hashCode方法,即字符串内容相同,hashCode值相同。但较小概率存在hash碰撞,即内容不同hash值相同
- hash表
- jdk1.8之前:数组+链表
- jdk1.8之后:数组+链表+红黑树
- 数组将不同的hashCode值得元素进行了分组,链表hashCode值相同但元素的内容不同的元素进行了链接
- String重写了hashCode和equals方法了
- 树
- 二叉树(二叉排序树):本身有序(左小右大),树中各个节点的度不能超过2
- 满二叉树:二叉树除叶子节点外,其它每个节点的度都为2
- 完全二叉树:二叉树除去最后一层后为满二叉树,且最后一层依次从左到右分布
- 平衡二叉树(二叉搜索树/AVL树):任意节点下左子树减右子树的绝对值不超过1(又称平衡因子|BF|<2)
- 平衡二叉树的调整:左旋、右旋、左右旋、右左旋
- 红黑树:平衡二叉树的一种实现,其根节点与叶子节点必须为黑色,红色节点的孩子节点都是黑色
- 完全二叉树的存储:顺序存储,即从根节点开始,按照层次依次存储到数组中(二叉树补0后可转为完全二叉树)
- 完全二叉树的存储:链式存储,即从根节点开始,每个节点都由左孩子+数据+右孩子组成,最后联成链表
- 二叉树的遍历:由于每个节点都会经历三次访问,所以产生了先、中、后三种遍历方式(栈);最后还有一种层次遍历方式(队列)
三、TreeSet
- 有序,线程不安全,使用元素的自然顺序进行排序,其它引用类型要实现Comparable或Comparator接口
package com.la.demo01;
import java.util.Objects;
public class Student implements Comparable{
private int age;
private String name;
public Student(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
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 boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(age, name);
}
@Override
public int compareTo(Object o) {
Student student=(Student)o;
return this.getAge()-student.getAge();
}
}
package com.la.demo01;
import java.util.Comparator;
import java.util.HashSet;
import java.util.TreeSet;
public class TestHashSet {
public static void main(String[] args) {
HashSet<Student> students = new HashSet<>();
students.add(new Student(18,"张三"));
students.add(new Student(17,"李四"));
students.add(new Student(18,"张三"));
System.out.println(students);
TreeSet<Student> students1=new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge()-o2.getAge();
}
});
students1.add(new Student(12,"aa"));
students1.add(new Student(10,"aa"));
students1.add(new Student(17,"aa"));
System.out.println(students1);
}
}
四、LinkedHashSet
- 可预知迭代顺序的set集合,线程不安全,由hash表+双链表,有序
- 案例
package com.la.demo01;
import java.util.LinkedHashSet;
import java.util.Scanner;
public class TestLinkedHashSet {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一串字符");
String s = scanner.nextLine();
char[] chars = s.toCharArray();
LinkedHashSet set = new LinkedHashSet<>();
for (char aChar : chars) {
set.add(aChar);
}
StringBuilder stringBuilder = new StringBuilder();
for (Object o : set) {
stringBuilder.append(o);
}
System.out.println(stringBuilder);
}
}
五、Map
-
双列集合的顶层接口,键不能重复
-
常有方法
-
V put(K key, V value) 增加(键不存在时候)修改(键存在的时候)
V get(Object key) 根据键来获取值
V remove(Object key) 根据键删除键值对
boolean containsKey(Object key) 判断键是否存在
boolean containsValue(Object value) 判断值是否存在
void clear() 清除集合中所有的元素
boolean isEmpty() 判断是否为空
Set keySet() 获取所有的键
Collection values() 获取所有的值
Set<Map.Entry<K,V>> entrySet() 用于遍历map集合
int size() 获取集合的长度
-
-
测试
package com.la.demo01;
import java.util.HashMap;
import java.util.Set;
public class TestHashMap {
public static void main(String[] args) {
HashMap<Object, Object> map = new HashMap<>();
map.put(1,"xiaoming");
map.put(2,"xiaoming");
map.put(3,"xiaoming");
map.put(2,"xiaoming2");
System.out.println(map);
System.out.println(map.get(2));
System.out.println(map.size());
System.out.println(map.isEmpty());
Set<Object> objects = map.keySet();
System.out.println(objects);
System.out.println(map.values());
System.out.println(map.containsValue("xiaoming2"));
System.out.println(map.containsKey(1));
map.putAll(map);
System.out.println(map);
}
}
- Map的遍历方式
- 通过keySet()方法获取所有key,同get(key)获取所有value
- 通过entrySet方法,返回一个set集合,里面存储的一个entry对象,即把key-value包装成一个entry对象,通过遍历set集合获得每个entry对象,通过对象的getKey()方法获取可以,通过getValue()方法获取value
- 案例
public class Test04 {
public static void main(String[] args) {
Scanner Scanner input = new Scanner(System.in);
System.out.println("请输入一串字符");
String line = input.nextLine();
char[] arrays = line.toCharArray();
Map m = new HashMap();
for (int i=0;i<arrays.length;i++) {
m.put(arrays[i],(m.containsKey(arrays[i])) ? ((Integer) (m.get(arrays[i])))+1 :1); }
System.out.println(m);
}
}
六、练习
-
package com.la.demo02; import java.util.Objects; public class Person { private int age; private String name; public Person(int age, String name) { this.age = age; this.name = name; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return age == person.age && Objects.equals(name, person.name); } @Override public int hashCode() { return Objects.hash(age, name); } } package com.la.demo02; import com.la.demo01.Student; import java.util.HashSet; public class Work1 { public static void main(String[] args) { HashSet<Object> objects = new HashSet<>(); objects.add(new Student(15,"李四")); objects.add(new Student(12,"王五")); objects.add(new Student(15,"李四")); System.out.println(objects); } }
package com.la.demo02; import java.util.HashMap; public class Work2 { public static void main(String[] args) { String[] a={"黑龙江省","浙江省","江西省","广东省","福建省"}; String[] b={"哈尔滨","杭州","南昌","广东","福州"}; HashMap<Object, Object> map = new HashMap<>(); for (int i = 0; i <a.length; i++) { map.put(a[i],b[i]); } System.out.println(map); } }
package com.la.demo02; import java.util.Objects; public class Car { private int age; private String name; public Car(int age, String name) { this.age = age; this.name = name; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Car car = (Car) o; return age == car.age && Objects.equals(name, car.name); } @Override public int hashCode() { return Objects.hash(age, name); } @Override public String toString() { return "Car{" + "age=" + age + ", name='" + name + '\'' + '}'; } }
package com.la.demo02; import java.util.HashMap; import java.util.Map; import java.util.Set; public class Work3 { public static void main(String[] args) { HashMap<Object, Object> map = new HashMap<>(); map.put(new Car(12,"小花猫"),100); map.put(new Car(12,"小黑猫"),200); map.put(new Car(12,"小白猫"),300); Set<Map.Entry<Object, Object>> entries = map.entrySet(); for (Map.Entry<Object, Object> entry : entries) { System.out.println(entry.getKey().toString()+entry.getValue()); } Set<Object> objects = map.keySet(); for (Object object : objects) { System.out.println(object.toString()+map.get(object)); } } }
4
package com.la.demo02; import java.util.ArrayList; import java.util.List; public class Work4 { public static void main(String[] args) { List<String> objects = new ArrayList<>(); objects.add("张三"); objects.add("李四"); objects.add("王五"); objects.add("二丫"); objects.add("钱六"); objects.add("孙七"); for (int i = 0; i < objects.size(); i++) { if (objects.get(i).equals("二丫")){ objects.set(i,"王小丫"); } } System.out.println(objects); } }
5
package com.la.demo02; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; public class Work5 { public static void main(String[] args) { Set<Object> objects = new LinkedHashSet<>(); objects.add("王昭君"); objects.add("王昭君"); objects.add("西施"); objects.add("杨玉环"); objects.add("貂蝉"); for (Object object : objects) { System.out.println(object); } Iterator<Object> iterator = objects.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } } }