国内ui网站有哪些,做app和网站怎样,wordpress如何检测加载缓慢的原因,ppt模板下载免费版网站文章目录 Set概述哈希值HashSet去重原理LinkedHashSetTreeSet自定义排序规则 Map概述Map的基本方法Map集合的获取功能哈希表HashMap底层源码 特点注意 Set
概述
Set集合也是一个接口#xff0c;继承自Collection#xff0c;与List类似#xff0c;都需要通过实现类来进行操… 文章目录 Set概述哈希值HashSet去重原理LinkedHashSetTreeSet自定义排序规则 Map概述Map的基本方法Map集合的获取功能哈希表HashMap底层源码 特点注意 Set
概述
Set集合也是一个接口继承自Collection与List类似都需要通过实现类来进行操作。 特点
不允许包含重复的值没有索引就不能使用普通的for循环进行遍历
import java.util.HashSet;
import java.util.Set;public class Demo01 {public static void main(String[] args) {//使用多态父类的引用指向子类对象SetString set new HashSet();//添加元素set.add(黄固);set.add(欧阳锋);set.add(段智兴);set.add(洪七公);set.add(段智兴);System.out.println(set);//打印集合//[洪七公, 黄固, 欧阳锋, 段智兴]//HashSet集合对于元素的读写顺序不做保证//相同的元素多次存储只能保留一个并且不会报错//List集合可以存储重复元素Set集合不行}
}例双色球
import java.util.Random;
import java.util.TreeSet;public class Demo02 {public static void main(String[] args) {Random ran new Random();//创建随机类对象int blueBall ran.nextInt(16) 1;
// HashSetInteger redBalls new HashSet();//创建集合用来存储红球TreeSetObject redBalls new TreeSet();//TreeSet集合自带排序规则while (redBalls.size() 6){redBalls.add(ran.nextInt(33) 1);//将当前生成的红球直接存进集合中//因为Set集合不能存储重复的元素所以去重的操作可以省略不做。}System.out.println(红球 redBalls 篮球 [ blueBall ]);}
}哈希值
Set集合的去重原理使用的是哈希值。 哈希值就是JDK根据对象地址 或者 字符串 或者数值 通过自己内部的计算出来的一个整数类型数据
public int hashCode() - 用来获取哈希值来自于Object顶层类
对象的哈希值特点
同一个对象多次调用hashCode()方法得到的结果是相同的。默认情况下不同的对象的哈希值也是不同的特殊情况除外
public class Demo03 {public static void main(String[] args) {//相同对象哈希值相同System.out.println(张三.hashCode());//774889System.out.println(张三.hashCode());//774889//不同对象哈希值不同System.out.println(new Object().hashCode());System.out.println(new Object().hashCode());//不同的对象的哈希值也有可能相同例外情况System.out.println(辂鹅.hashCode());//1179395System.out.println(较鸦.hashCode());//1179395System.out.println(辄鸇.hashCode());//1179395System.out.println(辅鷨.hashCode());//1179395}
}HashSet去重原理
HashSet集合的特点
底层结构是“哈希表”集合对于读写顺序不做保证没有索引Set集合中的内容不能重复
public class Demo04 {public static void main(String[] args) {HashSetStudent set new HashSet();//添加元素set.add(new Student(黄固,28));set.add(new Student(欧阳锋,38));set.add(new Student(段智兴,48));set.add(new Student(洪七公,40));set.add(new Student(段智兴,48));//从程序的角度来考虑两个段智兴不是同一个对象都有自己的存储空间所以哈希值也不一样。for (Student stu : set) {System.out.println(stu);}/*重写hashcode和equalsStudent{name段智兴, age48}Student{name欧阳锋, age38}Student{name洪七公, age40}Student{name黄固, age28}*/}
}LinkedHashSet
特点:
LinkedHashSet是哈希表和链表实现的Set接口具有可预测的读写顺序。有链表来保证元素有序有哈希表来保证元素的唯一性
public class Demo05 {public static void main(String[] args) {LinkedHashSetString set new LinkedHashSet();//添加元素set.add(黄固);set.add(欧阳锋);set.add(段智兴);set.add(洪七公);set.add(段智兴);//重复的元素不能存进去System.out.println(set);//打印集合 [黄固, 欧阳锋, 段智兴, 洪七公]}
}TreeSet
TreeSet集合底层实际上是一个TreeMapTreeMap集合底层是一个二叉树。放到TreeSet集合中的元素等同于放到TreeMap集合key部分了。TreeSet集合中的元素无序不可重复但是可以按照元素的大小顺序自动排序。
import java.util.TreeSet;
public class TreeSetTest02 {public static void main(String[] args) {// 创建一个TreeSet集合TreeSetString ts new TreeSet();// 添加Stringts.add(zhangsan);ts.add(lisi);ts.add(wangwu);ts.add(zhangsi);ts.add(wangliu);// 遍历for(String s : ts){// 按照字典顺序升序System.out.println(s);}/*lisiwangliuwangwuzhangsanzhangsi*/TreeSetInteger ts2 new TreeSet();ts2.add(100);ts2.add(200);ts2.add(900);ts2.add(800);ts2.add(600);ts2.add(10);for(Integer elt : ts2){// 升序System.out.println(elt);}}
}自定义排序规则
对于自定义的类无法排序因为类中对象之间没有比较规则不知道谁大谁小。
import java.util.TreeSet;public class TreeSetTest04 {public static void main(String[] args) {Customer c1 new Customer(32);Customer c2 new Customer(20);Customer c3 new Customer(30);Customer c4 new Customer(25);// 创建TreeSet集合TreeSetCustomer customers new TreeSet();// 添加元素customers.add(c1);customers.add(c2);customers.add(c3);customers.add(c4);// 遍历for (Customer c : customers){System.out.println(c);}}
}// 放在TreeSet集合中的元素需要实现java.lang.Comparable接口。
// 并且实现compareTo方法。equals可以不写。
class Customer implements ComparableCustomer{int age;public Customer(int age){this.age age;}// 需要在这个方法中编写比较的逻辑或者说比较的规则按照什么进行比较// k.compareTo(t.key)// 拿着参数k和集合中的每一个k进行比较返回值可能是0 0 0// 比较规则最终还是由程序员指定的例如按照年龄升序。或者按照年龄降序。Overridepublic int compareTo(Customer c) { // c1.compareTo(c2);return c.age - this.age;}public String toString(){return Customer[ageage];}
}匿名内部类方式
public class TreeSetTest05 {public static void main(String[] args) {
// TreeSetStudent ts new TreeSet();//默认排序规则TreeSetStudent ts new TreeSet(new ComparatorStudent() {Overridepublic int compare(Student o1, Student o2) {int res o1.getAge() - o2.getAge();return 0 res ? o1.getName().compareTo(o2.getName()) : res;//三目运算符 等于零用姓名排序}});//默认排序规则//添加元素ts.add(new Student(Andy,19));ts.add(new Student(Jack,18));ts.add(new Student(Tom,21));ts.add(new Student(Lucy,17));ts.add(new Student(Bob,21)); //当年龄相同时按照姓名的字典顺序排序for (Student stu : ts) {System.out.println(stu);}}
}Comparable和Comparator怎么选择呢 当比较规则不会发生改变的时候或者说当比较规则只有1个的时候建议实现Comparable接口。 如果比较规则有多个并且需要多个比较规则之间频繁切换建议使用Comparator接口。 Map
概述
双列集合用来存储键值对的集合。
interface MapK,V : K(key)键 V(value)值将键映射到值的对象不能出现重复的键每个键最多可以映射到一个值 1、Map和Collection没有继承关系。 2、Map集合以key和value的方式存储数据键值对 key和value都是引用数据类型。 key和value都是存储对象的内存地址。 key起到主导的地位value是key的一个附属品。 Map的基本方法
方法名说明V put(K key,V value)设置键值对V remove(Object key)删除元素void clear()清空集合boolean containsKey(Object key)判断键是否存在存在则返回trueboolean containsValue(Object value)判断值是否存在存在则返回trueboolean isEmpty()判断集合是否为空int size()获取集合元素个数
import java.util.HashMap;
import java.util.Map;public class Map01 {public static void main(String[] args) {MapString,String map new HashMap();map.put(STU001,Andy);map.put(STU002,Jack);map.put(STU003,Tom);map.put(STU004,Bob);map.put(STU004,Smith);//设置修改//如果键不存在则表示添加元素。如果键存在则表示设置值。//删除System.out.println(map.remove(STU003)); //Tom//判断是否包含System.out.println(map.containsKey(STU003)); //falseSystem.out.println(map.containsKey(STU004)); //trueSystem.out.println(-----------------------);System.out.println(map.containsValue(Tom)); //falseSystem.out.println(map.containsValue(Smith)); //trueSystem.out.println(-----------------------);System.out.println(map.isEmpty());//判断集合是否为空 falsemap.clear();//清空集合System.out.println(map.isEmpty()); //trueSystem.out.println(map); //{}}
}Map集合的获取功能
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;public class map_get {public static void main(String[] args) {MapString,String map new HashMap();map.put(STU001,Andy);map.put(STU002,Jack);map.put(STU003,Tom);map.put(STU004,Bob);//get通过键获取值System.out.println(map.get(STU003));System.out.println(------------------);//keySet 获取所有键的Set集合SetString keySet map.keySet();System.out.println(keySet);//values 获取所有值的Collection集合CollectionString values map.values();System.out.println(values);//entrySet 获取所有键值对对象的Set集合SetMap.EntryString, String es map.entrySet();//Map集合通过entrySet()方法转换成的这个Set集合Set集合中元素的类型是 Map.EntryK,V//Map.Entry和String一样都是一种类型的名字只不过Map.Entry是静态内部类是Map中的静态内部类System.out.println(es);//[STU001Andy, STU003Tom, STU002Jack, STU004Bob]for (Map.EntryString, String entry:es){System.out.println(key:entry.getKey() value:entry.getValue());}/*key:STU001 value:Andykey:STU003 value:Tomkey:STU002 value:Jackkey:STU004 value:Bob*/}
}哈希表
通过 数组 链表 实现的一种数据结构
哈希表的构造方法的参数是一个长度为16个元素的数组通过哈希值 % 16 的值作为头节点在数组中选择对应的位置就形成了哈希表。
HashMap
底层源码 public class HashMap{// HashMap底层实际上就是一个数组。一维数组NodeK,V[] table;// 静态的内部类HashMap.Nodestatic class NodeK,V {final int hash; // 哈希值哈希值是key的hashCode()方法的执行结果。hash值通过哈希函数/算法可以转换存储成数组的下标。final K key; // 存储到Map集合中的那个keyV value; // 存储到Map集合中的那个valueNodeK,V next; // 下一个节点的内存地址。}}特点 1、无序不可重复。 为什么无序 因为不一定挂到哪个单向链表上。 不可重复是怎么保证的 equals方法来保证HashMap集合的key不可重复。 如果key重复了value会覆盖。 2、放在HashMap集合key部分的元素其实就是放到HashSet集合中了。 所以HashSet集合中的元素也需要同时重写hashCode()equals()方法。 3、HashMap集合的默认初始化容量是16默认加载因子是0.75 这个默认加载因子是当HashMap集合底层数组的容量达到75%的时候数组以二叉树开始扩容。
重点记住HashMap集合初始化容量必须是2的倍数这也是官方推荐的 这是因为达到散列均匀为了提高HashMap集合的存取效率所必须的。
注意 1.向Map集合中存以及从Map集合中取都是先调用key的hashCode方法然后再调用equals方法 equals方法有可能调用也有可能不调用。 拿put(k,v)举例什么时候equals不会调用 k.hashCode()方法返回哈希值 哈希值经过哈希算法转换成数组下标。 数组下标位置上如果是nullequals不需要执行。 拿get(k)举例什么时候equals不会调用 k.hashCode()方法返回哈希值 哈希值经过哈希算法转换成数组下标。 数组下标位置上如果是nullequals不需要执行。 4.假设将所有的hashCode()方法返回值固定为某个值那么会导致底层哈希表变成了 纯单向链表。 这种情况我们成为散列分布不均匀。什么是散列分布均匀 假设有100个元素10个单向链表那么每个单向链表上有10个节点这是最好的 是散列分布均匀的。假设将所有的hashCode()方法返回值都设定为不一样的值可以吗有什么问题 不行因为这样的话导致底层哈希表就成为一维数组了没有链表的概念了。 也是散列分布不均匀。散列分布均匀需要你重写hashCode()方法时有一定的技巧。