数据结构,set接口,Map接口

一,数据结构简介

常见的数据结构
数据存储的常用结构有:栈、队列、数组、链表和红黑树

栈:
栈:stack,又称堆栈,它是运算受限的线性表,其限制是仅允许在标的一端进行插入和删除操作,不允许在其他任何位置进行添加、查找、删除等操作。
特点:
①先进后出(即,存进去的元素,要在后它后面的元素依次取出后,才能取出该元素)。
②栈的入口、出口的都是栈的顶端位置。
注意:
入栈:也称为压栈,就是存元素。
出栈:也称为弹栈,就是取元素。

队列
队列:queue,简称队,它同堆栈一样,也是一种运算受限的线性表,其限制是仅允许在表的一端进行插入,而在表的另一端进行删除。
特点:
①先进先出(即,存进去的元素,要在后它前面的元素依次取出后,才能取出该元素)。
②队列的入口、出口各占一侧。

数组
数组:Array,是有序的元素序列,数组是在内存中开辟一段连续的空间,并在此空间存放元素。就像是一排出租屋,有100个房间,从001到100每个房间都有固定编号,通过编号就可以快速找到租房子的人。

特点:
①查找快(通过索引,可以快速访问指定位置的元素)。
②增删慢(指定索引位置增加元素:需要创建一个新数组,将指定新元素存储在指定索引位置,再把原数组元素根据索引,复制到新数组对应索引的位置。删除同理)。在堆内存中,频繁的创建数组,复制数组中的元素,销毁数组,效率低下。

链表:
链表:linked list,由一系列结点node(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。我们常说的链表结构有单向链表与双向链表,那么这里给大家介绍的是单向链表。

特点:
①多个结点之间,通过地址进行连接。
②查询慢(链表中的地址并不一定是连续的,所以每次查询需要重头开始)。
③增删快(增加和删除对于链表整体没有影响,只需要修改连接下个元素的地址即可。删除同理)。

链表的结构:
链表中的每一个元素也称之为一个节点,一个节点包含了一个数据源(存储数组),两个指针(存储地址)。

红黑树
在这里插入图片描述

二,set接口

`java.util.Set`接口和`java.util.List`接口一样,同样继承自`Collection`接口,
它与`Collection`接口中的方法基本一致,并没有对`Collection`接口进行功能上
的扩充,只是比`Collection`接口更加严格了。与`List`接口不同的是,
`Set`接口中元素无序,并且都会以某种规则保证存入的元素不出现重复。

 Set接口的特点
①不允许存储重复的元素
	②没有索引,没有带索引的方法,也不能使用普通的for循环遍历;可以采用:迭代器、增强for。

HashSet集合介绍
`java.util.HashSet`是`Set`接口的一个实现类,它所存储的元素是
不可重复的,并且元素都是无序的(即存取顺序不一致)。
`java.util.HashSet`底层的实现其实是一个`java.util.HashMap`支持,做了解。

 HashSet的特点
     ①不允许存储重复的元素
     ②没有索引,没有带索引的方法,也不能使用普通的for循环遍历
     ③是一个无序的集合,存储元素和取出元素的顺序有可能不一致
     ④底层是一个哈希表结构(查询的速度非常的快)

注意:HashSet是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于:hashCodeequals方法。

//创建一个Set接口
Set<Integer> set = new HashSet<>();
//使用add方法往集合中添加元素
set.add(1);
set.add(3);
set.add(2);
set.add(1);//已经存在的元素,不会被存储
//使用迭代器遍历set集合
Iterator<Integer> it = set.iterator();
while (it.hasNext()){
    Integer n = it.next();
    System.out.println(n);//1,2,3
}
//使用增强for遍历set集合
System.out.println("-----------------");
for (Integer i : set) {
    System.out.println(i);
}
hashCode
①哈希值:是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来得到地址,不是数据实际存储的物理地址)
②在Object类有一个方法,可以获取对象的哈希值 int hashCode() 返回该对象的哈希码值。
    ③hashCode方法:public native int hashCode();native:代表该方法调用的是本地操作系统的方法



 LinkedHashSet
在HashSet下面有一个子类`java.util.LinkedHashSet`,它是链表和哈希表组合的一个数据存储结构。

2.5.1 LinkedHashSet集合特点:
    底层是一个哈希表(数组+链表/红黑树)+链表:多了一条链表(记录元素的存储顺序),保证元素有序。
public class LinkedHashSetDemo {
    public static void main(String[] args) {
        Set<String> set = new LinkedHashSet<String>();
        set.add("bbb");
        set.add("aaa");
        set.add("abc");
        set.add("bbc");
        Iterator<String> it = set.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }
}

三,Map接口

在这里插入图片描述
Collection中的集合,元素是孤立存在的(理解为单身),向集合中存储元素采用一个个元素的方式存储。
Map中的集合,元素是成对存在的(理解为夫妻)。每个元素由键与值两部分组成,通过键可以找对所对应的值。
Collection中的集合称为单列集合,Map中的集合称为双列集合。
④需要注意的是,Map中的集合不能包含重复的键,值可以重复;每个键只能对应一个值。

 Map常用子类
通过查看Map接口描述,看到Map有多个子类,这里我们主要讲解常用的HashMap集合、LinkedHashMap集合。
①HashMap<K,V>:存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。
②LinkedHashMap<K,V>:HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构。通过链表结构可以保证元素的存取顺序一致;通过哈希表结构可以保证的键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。

注意:Map接口泛型变量中的集合都有两个<K,V>,在使用时,要为两个泛型变量赋予数据类型。两个泛型变量<K,V>的数据类型可以相同,也可以不同。

Map接口中的常用方法
Map接口中定义了很多方法,常用的如下:
public V put(K key, V value): 把指定的键与指定的值添加到Map集合中。
public V remove(Object key): 把指定的键所对应的键值对元素 在Map集合中删除,返回被删除元素的值。
public V get(Object key):根据指定的键,在Map集合中获取对应的值。
boolean containsKey(Object key):判断集合中是否包含指定的键。
public Set<K> keySet(): 获取Map集合中所有的键,存储到Set集合中。
⑥ `public Set<Map.Entry<K,V>> 获取到Map集合中所有的键值对对象的集合(Set集合)。

注意:
使用put方法时,若指定的键(key)在集合中没有,则没有这个键对应的值,
返回null,并把指定的键值添加到集合中; 若指定的键(key)在集合中存
在,则返回值为集合中键对应的值(该值为替换前的值),并把指定键所对应的值,替换成指定的新值。 

 Map集合遍历键找值方式
键找值方式:即通过元素中的键,获取键所对应的值
步骤:
1. 获取Map中所有的键,由于键是唯一的,所以返回一个Set集合存储所有的键。
2. 遍历键的Set集合,得到每一个键。
3. 根据键,获取键所对应的值。
//获取所有的键
Set<String> keys = map.keySet();
// 遍历键集 得到每一个键
for (String key : keys) {
    //通过键获取对应值
    String value = map.get(key);
    System.out.println(key+"的CP是:"+value);
}
 1.6 Map集合遍历键值对方式
键值对方式:即通过集合中每个键值对(Entry)对象,获取键值对(Entry)对象中的键与值
操作步骤:
①获取Map集合中,所有的键值对(Entry)对象,以Set集合形式返回。
②遍历包含键值对(Entry)对象的Set集合,得到每一个键值对(Entry)对象。
③通过键值对(Entry)对象,获取Entry对象中的键与值。
// 创建HashMap集合对象
HashMap<String, String> map = new HashMap<String,String>();
// 添加元素到集合
map.put("胡歌", "霍建华");
map.put("郭德纲", "于谦");
map.put("薛之谦", "大张伟");
// 获取 所有的 entry对象  entrySet
Set<Map.Entry<String,String>> entrySet = map.entrySet();
// 遍历得到每一个entry对象
for (Map.Entry<String, String> entry : entrySet) {
    String key = entry.getKey();
    String value = entry.getValue();
    System.out.println(key+"的CP是:"+value);
}

注意:
Map集合不能直接使用迭代器或者foreach进行遍历。但是转成Set之后就可以使用了。

1.7  HashMap存储自定义类型键值
     练习:每位学生(姓名,年龄)都有自己的家庭住址。那么,既然有对应关系,则将学生对象和家庭住址存储到 map集合中。学生作为键, 家庭住址作为值。(注意,学生姓名相同并且年龄相同视为同一名学生。)
①当给HashMap中存放自定义对象时,如果自定义对象作为key存在,这时要保证对象唯一,必须复写对象的 hashCode和equals方法。 
②如果要保证map中存放的key和取出的顺序一致,可以使java.util.LinkedHashMap 集合来存放。

LinkedHashMap
我们知道HashMap保证成对元素唯一,并且查询速度很快,可是成对元素存放进去是没有顺序的,那么我们要保证有序,还要速度快怎么办呢? 在HashMap下面有一个子类LinkedHashMap,它是链表和哈希表组合的一个数据存储结构。
代码实例:

public static void main(String[] args) {
    LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
    map.put("邓超", "孙俪");
    map.put("李晨", "范冰冰");
    map.put("刘德华", "朱丽倩");
    Set<Entry<String, String>> entrySet = map.entrySet();
    for (Entry<String, String> entry : entrySet) {
        System.out.println(entry.getKey() + " " + entry.getValue());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值