容器2(HashSet、HashMap、迭代器、Collections工具类(Comparable&comparator))

在这里插入图片描述

一、HashSet

Set接口下有一个 HashSet 实现类,HashSet的底层是用 HashMap 实现的( 看了 HashMap后再回来看HashSet的实现 ),因此,查询效率高。由于采用Hashcode算法直接确定元素的内存地址,增删效率也高。
HashSet 接口中的元素 无序不可重复 ,不包含重复元素,最多包含一个 null,元素没有顺序 。

1. 无序

元素的存储顺序,不由存放顺序而定,容器有自己的一套存放顺序的规则。

2.遍历

不能用普通for循环遍历,因为Set集合的元素是没有下标的,不可以通过下标获取

		System.out.println("======增强for循环=====");
        for (String str:set){
            System.out.println(str);
        }
        System.out.println("-------迭代器遍历------");
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

3.不可重复

添加元素之前,就已经经过了判断。判断是否相等先走 hashCode 方法,如果hashCode方法返回值相同,再走 equals 方法进一步比较.如果不想让属性相同的javaBean对象存储在hashSet中,javaBean类应重写HashCode和equals方法。

二、Map接口

在这里插入图片描述
Map只是一个接口,其中提供了Map的规范,即各种方法的定义

Object put(Object key, Object value); //添加元素
Object get(Object key); //根据key获取value
Object remove(Object key); //根据key删除一个元素
boolean containsKey(Object key); //判断map中是否有该key
boolean containsValue(Object value);//判断map中是否有该value
int size(); //查看元素的个数
boolean isEmpty(); //判断元素是否为空
void putAll(Map t); //将一个map添加到另一个map中
void clear();//情况map

注意:如果存入的键值对中key相同,那么后面的会覆盖掉前面的当数据存放到Map之后,我们是无法控制存放数据的顺序的

1.hashMap的使用

//Map接口的特点,key不允许重复,值可以重复,而且key是无序的
  //创建集合对象
  HashMap hm=new HashMap();
  //(1)添加元素
  hm.put("hello", 123);//123自动装箱成Integer类,集合不允许出现基本数据类型
  hm.put("world", 456);
  hm.put("hello", 1000);//集合去添加元素的时候它的键(key)是不允许重复的,如果重复将进行键的覆盖
  hm.put("java", 1000);//值可以重复(1000)
   
  System.out.println("集合中元素的个数:"+hm.size());
  System.out.println("集合是否为空:"+hm.isEmpty());
  System.out.println(hm);
  System.out.println(hm.remove("world"));//先输出后移除,只移除了键world,456还在
  System.out.println(hm);
  //判断
  //containsKey判断这个键是否存在
  System.out.println(hm.containsKey("java")+"\t"+hm.containsKey("world"));
  //containsValue判断这个值是否存在
  System.out.println(hm.containsValue(1000)+"\t"+hm.containsValue(2000));
   
  //获取元素,根据键去获取值
  System.out.println(hm.get("java")+"\t"+hm.get("world"));
   
  //获取所有键(key)的集合
  Set set=hm.keySet();
  //遍历所有键的内容
  for(Object obj:set){
   System.out.println(obj);
  }
  //获取所有值(value)的集合
  System.out.println("\n---------------------- ");
  Collection coll=hm.values();
  //遍历所有值的类型
  for(Object obj:coll){
   System.out.println(coll);
  }
  //获取所有key-value关系的集合
  Set entrySet=hm.entrySet();
  for(Object obj:entrySet){
   System.out.println(obj);
  }
   

HashMap中存储数据的特点:

  • 存储的元素是以K-V的形式存在的
  • map集合中 key 必须要唯一,如果添加了相同的键值对(键相同)会发生覆盖
  • map集合中元素(键值对)是无序的,和Set集合类似

2.HashMap与Hashtable的区别

/**
   * HashMap与Hashtable
   * 区别:
   * (1)版本不同 HashMap JDK1.2  Hashtable JDK1.0
   * (2)HashMap继续了AbstractMap,实现了Map接口,Hashtable继承了Dictionary实现Map接口
   * (3)HashMap允许null值和null键,但是null作为key只允许以一个,Hashtable非null的键和值
   * (4)HashMap是线程不同步的(效率高,安全性低),Hashtable是线程同步的(效率低,安全性高)
   */

遍历HashMap

		Map<String, String> map = new HashMap<>();
			map.put("1","一,壹,Ⅰ");
			map.put("2","二,贰,Ⅱ");
		   	map.put("3","三,叁,Ⅲ"); 
        //遍历map集合
        Set<Entry<String, Integer>> entries = map.entrySet();
        //迭代器
        System.out.println("=========迭代器===============");
        Iterator<Entry<String, Integer>> iterator = entries.iterator();
        while (iterator.hasNext()){
            Entry<String, Integer> entry = iterator.next();
            System.out.println(entry.getKey()+"-->"+entry.getValue());
        }

        //增强for循环
        System.out.println("=========增强for循环===============");
        for (Entry<String,Integer> entry:entries){
            System.out.println(entry.getKey()+"-->"+entry.getValue());
        }

        //keySet
        System.out.println("========KeySet===========");
        Set<String> keys = map.keySet();
        for (String key:keys){
            System.out.println(key+"-->"+map.get(key));
        }

注意: 如果存入的键值对中key相同,那么后面的会覆盖掉前面的当数据存放到Map之后,我们是无法控制存放数据的顺序的

3. hashMap底层原理

1.哈希表的结构和特点
hashtable 也叫散列表
特点:快 很快 神奇的快
结构:结构有多种
最流行、最容易理解:顺序表+链表
主结构:顺序表
每个顺序表的节点在单独引出一个链表
2.哈希表是如何添加数据的
1.计算哈希码(调用 hashCode(),结果是一个 int 值,整数的哈
希码取自身即可)
2.计算在哈希表中的存储位置 y=k(x)=x%11 x:哈希码 k(x)
函数 y:在哈希表中的存储位置
3.如何减少冲突
因此,一般情况下,装填因子取经验值 0.5
4.哈希函数的选择
直接定址法 平方取中法 折叠法 除留取余法(y = x%11)查询相关资料
JDK1.8 开始,当链表的个数>=8 时,就会将链表转为红黑树,
目的是为了减少查询比较的次数。
在这里插入图片描述
在这里插入图片描述
表象看集合里面数据的特征:
List(ArrayList,LinkedList):单个数据,数据是可以重复的,而且可以指定位置
Set:单个数据,数据是不可以重复,而且是无序的(不由用户来指定位置|顺序)
Map:成键值对的数据,数据是没有顺序的,键是不可以重复的
hashCode在Set和Map集合中判断对象是否重复(相同)
equals也是用来判断对象是否相同(重复)List,Set,Map

三、迭代器

所有实现了Collection接口的容器类都有一个 iterator 方法用以返回一个实现了Iterator接口的对象。
Iterator对象称作迭代器,用以方便的实现对容器内元素的遍历操作。
Iterator接口定义了如下方法:

1.Iterator

boolean hasNext(); //判断是否有元素没有被遍历 
Object next(); //返回游标当前位置的元素并将游标移动到下一个位置 
void remove(); //删除游标左面的元素,在执行完next之后该 ,操作只能执行一次

在这里插入图片描述

		Iterator<Student> iterator = list.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }

2.ListIterator

相比于Iterator,collection.listIterator([index])方法可以给定index使指针指向具体的位置,listIterator多了hasPrevious()、previous()等方法完成集合的倒叙遍历。

ListIterator<Student> listIterator = list.listIterator(list.size());
        while (listIterator.hasPrevious()) {
            System.out.println(listIterator.previous());
        }

四、Collections工具类

void sort(List) //对List容器内的元素排序,排序的规则是按照升序进行排序。 
void shuffle(List) //对List容器内的元素进行随机排列 
void reverse(List) //对List容器内的元素进行逆续排列 
void fill(List, Object) //用一个特定的对象重写整个List容器 
int binarySearch(List, Object)//对于顺序的List容器,采用折半查找的方法查找 特定对象

上述中collections工具类中的某些方法用于对集合中的对象进行排序
问题:上述方法根据什么确定集合中对象大小顺序?
所有可以“排序”的类都实现了 java.lang.Comparable 接口, Comparable 接口中只有一个方法 public int compareTo(Object obj)

1.Comparable接口

返回 0 表示 this == obj
返回正数表示 this > obj 
返回负数表示 this < obj 

实现了Comparable 接口的类通过实现 comparaTo 方法从而确定该类对象的排序方式。

//使用工具类对集合进行排序
public class CollectionTest {
    public static void main(String[] args) {
        List<Student> list=new ArrayList<>();
        Student student=new Student(18,"张三",55.5);
        Student student2=new Student(18,"李四",44.4);
        Student student3=new Student(20,"王五",66.6);
        list.add(student2);
        list.add(student);
        list.add(student3);
        
        System.out.println(list);
        Collections.sort(list);
        System.out.println(list);
    }
}

//实现Comparable接口,重写compareTo方法,确定比较规则
public class Student implements Comparable<Student>{
    private int age;
    private String name;
    private double weight;

    public Student(int age, String name, double weight) {
        this.age = age;
        this.name = name;
        this.weight = weight;
    }

    public Student() {
    }
    
    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", weight=" + weight +
                '}';
    }

    @Override
    public int compareTo(Student o) {
        // 0   1(没变)  -1(倒序)
        //如果年龄不能,则按年龄排序;若年龄相等,则按体重排序
        if (this.age==o.age){
          return   (this.weight < o.weight) ? -1 : ((this.weight == o.weight) ? 0 : 1);
        }else {
            return (this.age < o.age) ? -1 : ((this.age == o.age) ? 0 : 1);
        }
    }
}

2.Comparator接口

除了javaBean类实现comparable接口并重新compareTo方法之外,也可以定义一个类去实现Comparator接口并重写起compare方法。然后在对集合排序时,给定自定义的比较类

//比较器
class MyCor implements Comparator<Student>{

    @Override
    public int compare(Student o1, Student o2) {
    			//按照年龄排序
        return o1.getAge()-o2.getAge();
    }
}
public static void main(String[] args) {
        List<Student> list=new ArrayList<>();
        Student student=new Student(17,"张三",55.5);
        Student student2=new Student(18,"李四",44.4);
        Student student3=new Student(20,"王五",66.6);
        list.add(student2);
        list.add(student);
        list.add(student3);
        //对集合排序时,给定具体的比较器对象
        Collections.sort(list,new MyCor());
        System.out.println(list);
     
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值