赞
踩
Set继承自Collection接口,没有特殊的方法
HashSet概述:
元素放入时是无序的,指的是内存空间不连续,因为元素在set中的位置是由该元素的HashCode决定的。
而且,HashMap每次扩容都可能导致元素重新排布,所以元素的位置是不确定的。
TreeSet概述:
存入TreeSet集合中的元素要具备比较性,比较性要实现Comparable接口,重写该接口的compareTo方法。
TreeSet根据构造方法不同,分为自然排序(无参构造)和比较器排序(有参构造):
自然排序要求元素必须实现Compareable接口,并重写里面的compareTo()方法,元素通过比较返回的int值来判断排序序列,返回0说明两个对象相同,不需要存储。
比较器排需要在TreeSet初始化是时候传入一个实现Comparator接口的比较器对象,或者采用匿名内部类的方式new一个Comparator对象,重写里面的compare()方法。
LinkedHashSet底层数据结构是哈希表和链表,根据元素的hashCode值来决定元素的存储位置,但它同时使用链表维护元素的次序,这样使得元素看起来是以插入的顺序保存的,也就是说当遍历集合LinkedHashSet集合里的元素时,集合将会按元素的添加顺序来访问集合里的元素。
输出集合里的元素时,元素顺序总是与添加顺序一致。但是LinkedHashSet依然是HashSet,因此它不允许集合重复。
Set集合代码:
- package com.easy722;
-
- import com.text.TextA;
-
- import java.util.*;
-
- public class EasySet {
- //set集合
- //List集合是有序的,set集合是无序的
- //有序和无序 取出的顺序和添加的顺序是一样的
- public static void main(String[] args) {
- //实例化Set集合
- HashSet set=new HashSet();
- set.add("23");
- set.remove("123");
- set.size();
- set.add("23");
- int size=set.size();//1
- System.out.println(size);
- //set中不能存储相同的数据
- set.add(new String("456"));
- set.add(new String("456"));
- size=set.size();//2
- System.out.println(size);
- //可以存储null值
- set.add(null);
- size=set.size();//3
- System.out.println(size);
- for (Object item:set){
- System.out.println(item);
- }
-
- //TreeSet 红黑树
- TreeSet test=new TreeSet();
- //存入数据
- test.add(2);
- test.add(200);
- test.add(3);
- test.add(88);
- test.add(45);
- test.add(72);
- test.add(1);
- test.add(99);
- //同样一个TreeSet存储的内容都应该是可比较的
- //默认情况下不能存储不同类型
- //test.add("234");
- //不能存null值
- //test.add(null);
- //无序的
- //遍历
- for (Object item:test){
- System.out.print(item+",");
- }
- System.out.println();
- //先序遍历 中序遍历 后序遍历
- //TreeSet遍历方式是中序方式
-
- //TreeSet 内部使用二叉树 内部节点是可以比较大小的
-
- Comparator<Student> com=(a,b)-> {
- if(a.score==b.score){
- return 0;
- }
- return a.score > b.score ? 1 : -1;
- };
- TreeSet<Student> ttset=new TreeSet<>(com);
- Student stua=new Student();stua.score=89;
- Student stub=new Student();stub.score=80;
- Student stuc=new Student();stuc.score=99;
- Student stud=new Student();stud.score=100;
-
- ttset.add(stua);
- ttset.add(stub);
- ttset.add(stuc);
- ttset.add(stud);
- for(Student stu:ttset){
- System.out.println(stu.score);
- }
- //LinkedHashSet 是有序的集合Set
-
- }
- }
- class Student implements Comparable{
- int score;
-
- @Override
- public int compareTo(Object o) {
- if (o instanceof Student){
- Student item=(Student)o;
- if(this.score==item.score)
- return 0;
- return this.score>item.score?1:-1;
- }else{
- //如果o对象不是Student 就无法比较 这是程序运行时出现的特殊情况
- //异常情况 我们的方法处理不了这种情况,就要抛出一个异常对象
- //告知调用此方法发代码
- throw new RuntimeException("传入对象不可比较");
- }
- }
- }

Map 存储键值对 键 就是名字 值 存储的对象
Map接口是一个键值对的集合,它继承自Collection接口中的size()和isEmpty()等方法,同时还提供了根据键查找值的方法,以及添加、删除和更新键值对的方法。在Java中,Map接口有几个常见的实现类,每个实现类都具有不同的性能和用途。
HashMap:基于哈希表实现,具有快速的查找和插入操作,适用于需要快速查找键值对的场景。
TreeMap:基于红黑树实现,可以对键进行排序,并提供了一系列与排序相关的方法,适用于需要对键进行排序的场景。
LinkedHashMap:基于哈希表和链表实现,保持键值对的插入顺序,适用于需要保持插入顺序的场景。
底层实现:数组加列表,数组的默认容量是16,每次扩容2倍,扩容阈值是0.75,一个链达到8就对该链进行树化,一支树上的元素低于6个,这个树就会退化成链,最小树化容量阈值 64 就是数组容量最少64且链上最少是8个才树化,如果数组的长度没有达到64,优先扩容。
put(K key, V value): 将指定的键值对添加到HashMap中。
remove(Object key): 从HashMap中移除指定键的键值对。
get(Object key): 返回指定键对应的值。
containsKey(Object key): 检查HashMap中是否包含指定的键。
containsValue(Object value): 检查HashMap中是否包含指定的值。
size(): 返回HashMap中键值对的数量。
在HashMap中key和value可以是null,但是key不能重复,而在Tree Map中,key应该可以比较,且不能是null值。Hash table的key和value都不能是null,Hashtable是线程安全的集合。
ConcurrentHashMap 线程安全且效率较高。
线程安全的Map Hashtable ConcurrentHashMap(性能优异,锁颗粒度比较小)
代码:
- package com.easy722;
-
- import java.util.*;
- import java.util.concurrent.ConcurrentHashMap;
-
- public class EasyMap {
- //Map 存储键值对 键 就是名字 值 存储的对象
- public static void main(String[] args) {
- Map map= new HashMap();
- //存储数据
- map.put("A1","张三");
- //可以通过存入的key获取存入的对象
- Object obj=map.get("A1");//获取A1对应的value值
- System.out.println(obj);//张三
- //通过key删除键值对
- Object rem_obj=map.remove("A1");
- System.out.println(rem_obj);//张三 返回删除的value值
- //是否包含key
- map.containsKey("A1");
- //是否包含value
- map.containsValue("张三");
- Set setkey=map.keySet();//获取所有的key
- //获取所有的value
- Collection con=map.values();
- //key和value可以是null,但是key不能重复
- map.put(null,null);
- map.put("A1","张三");
- map.put("A1",null);
- System.out.println(map);//{null=null, A1=null}null将张三覆盖,key是唯一的
-
-
- //TreeMap
- //key应该是可比较的
- //key不能是null值
- Hashtable ht=new Hashtable();
- ht.put("t1","张三");
- //Hashtable key和value都不能是null
- //Hashtable是线程安全的集合
- LinkedHashMap lMap=new LinkedHashMap();
- lMap.put("","");
-
- //ConcurrentHashMap 线程安全 效率较高
- ConcurrentHashMap chm;
-
- //HashMap 底层实现 数组加链表
- HashMap hmap=new HashMap();
- hmap.put("","");
- //HashMap 的数组默认容量 16
- //每次扩容 2倍
- //扩容阈值 0.75
- //一个链达到8就对该链进行树化
- //一支树上的元素低于6个,这个树就会退化成链
- //最小树化容量阈值 64 就是数组容量最少64且链上最少是8个才树化
- //如果数组的长度没有达到64,优先扩容
-
- //线程安全的Map Hashtable ConcurrentHashMap(性能优异,锁颗粒度比较小)
-
- }
-
-
- }

泛型是广泛的数据类型,确保类型安全的一种途径。
当创建一个 Generic< T > 类对象时,会向尖括号 <> 中传入具体的数据类型。
方法签名中声明了< 泛型标识>的方法称为泛型方法。只有在方法签名中声明了的方法才是泛型方法,仅使用了泛型类定义的类型参数的方法并不是泛型方法。
1、泛型类中的静态方法和静态变量不可以使用泛型类所声明的类型参数。
2、泛型方法可以是静态的,这一点容易和上面的点混淆。
3、使用了泛型类中的泛型标识的方法不一定是泛型方法,泛型方法必须必须由< T>泛型标识声明。即使泛型类中定义的类型参数标识和泛型方法中定义的类型参数标识都为< T > ,但它们彼此之间是相互独立的。也就是说,泛型方法始终以自己声明的类型参数为准,所以,在泛型类中定义泛型方法时最好用不同的标识来区分。
代码:
- package com.easy722;
-
- import java.util.*;
-
- public class EasyGenericity<J,M,N>{
- //泛型 广泛的数据类型
- //确保类型安全的一种途径
- //定义 类或方法上定义泛型
- private M m;
- public void test(M m,N n){
-
- }
- //在返回值前面声明
- public static <J extends List > J testA(J j){//就近原则,不是上面的J
- return j;
- }
- public static <A>void testAA (List<?super A>a){
-
- }
-
- public <E> E test(E e){
- //返回的类型和传入的类型是同一种
- return e;
- }
-
- public static void main(String[] args) {
- testA(new ArrayList());
- //testA(new HashSet());
- //类型安全
- List list=new ArrayList();
- list.add("123");
- //list.add(new Object());
-
- for (Object object:list){
- //类型转换的时候没有明确对象的数据类型进行强制数据类型转换
- //会抛出Class CaseException(类型转换异常)
- //类型不安全
- String str=(String)object;
- System.out.println(str);
- }
-
- List<String> listA=new ArrayList<>();
- listA.add("8");
-
- Map<String,Object> map=new HashMap<>();
-
-
- }
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。