Java中的集合

Java中的集合

集合:能够动态存放多个数据的存储结构,Java提供的一个公共API,存在于java.util包中

Java整个集合的架构如下:
在这里插入图片描述
主要有两个分支:

  • Collection 每次只能存入一个值 具体的存储性质和不同的子接口有关

    Set 存入的元素无序且不重复 常用实现类有

  1. HashSet 无序不重复的集合

  2. LinkedHashSet 有序不重复的集合 有序是通过链表方式实现

List 存入的元素有序且可以重复 常用实现类有:

  1. ArrayList 底层以数组方式实现 特点 读取效率高 但修改的效率较低 经常使用ArrayList
  2. LinkedList 底层以双向链表实现实现 特点 修改的效率高 但读取效率较低
  • Map 每次需要存入一个键值对

    常用实现类 HashMap

Collection

Collection是所有单个存储元素的一个顶级类 常用方法:

 •int size(); 返回此collection中的元素数。 

 •boolean isEmpty(); 判断此collection中是否包含元素。

 •boolean contains(Object obj); 判断此collection是否包含指定的元素。

 •boolean contains(Collection c); 判断此collection是否包含指定collection中的所有元素。 

 •boolean add(E element); 向此collection中添加元素。

 •boolean addAll(Collection c);将指定collection中的所有元素添加到此collection中 

 •boolean remove(Object element); 从此collection中移除指定的元素。

 •boolean removeAll(Collection c); 移除此collection中那些也包含在指定collection中的所有元 素。 

 •void clear(); 移除些collection中所有的元素。 

 •boolean retainAll(Collection c); 仅保留此collection中那些也包含在指定collection的元素。 

 •Iterator iterator(); 返回在此collection的元素上进行迭代的迭代器。 

 •T[] toArray(T[] arr); 把此collection转成数组。

Iterator

Iterator 是Collection的父级接口 内部提供了对于Collection类型的集合的遍历方式

常用方法:

  • hasNext() 查看当前指针的下一个位置是否有元素 如果有返回true 否则返回false
  • next() 移动指针到下一个元素 并获取该元素 返回给调用者
  • remove() 移除当前遍历的指针

自从JDK5开始,所有Iterator方式实现的变量都可以使用 forEach方式来进行遍历

Set接口

Set接口是Collection的一个子接口类型,它的特点是无序且不重复

Set集合与数学中“集合”的概念相对应

如何判定Set中的元素是否重复:

  1. 判定该对象的hashCode()方法返回的值是否相等 如果相等即判定当前两个对象相等 直接跳过该对象的存储步骤 如果不等则直接存入元表中
  2. 当hashCode() 返回的值相等时 再利用对象的equals()方法来判定当前两个对象是否相等 如果相等则跳过该存储不走 如果不等 则会将该存储的模块转换为链表形式进行存储 在JDK8后如果链表的长度达到8 则会将链表转换成一个红黑树结构进行存储 但此种方式很少会触发

根据对象的哈希码值计算出它的存储索引,在散列表的相应位置(表元)上的元素间进行少量的比较操作就可以找出它。

Set系的集合存、取、删对象都有很高的效率。

对于要存放到Set集合中的对象,对应的类一定要重写equals()和hashCode(Object obj)方法以实现对 象相等规则

常用子接口:

  • HashSet 不保存元素的存入顺序

底层是使用Hash表的形式进行存储数据的,所以读取效率较高,直接根据hash值读取对应的数据

  • LinkedHashSet 底层是链表 保证存入顺序 但依然不能重复

需要有序且不重复时使用 但效率略低

List接口

实现List接口的集合类中的元素是有序的,且允许重复

List集合中的元素都对应一个整数型的序号记载其在集合中的位置,可以根据序号存取集合中的元素。

JDK API所提供的List集合类常用的有:

  • ArrayList
  • LinkedList

常用的方法:

public Object get(int index) 返回列表中的元素数
public Object add(int index, Object element); 在列表的指定位置插入指定元素.将当前处于该位置的
元素(如果有的话)和所有后续元素向右移动
public Object set(int index, Object element) ; 用指定元素替换列表中指定位置的元素
public Object remove(int index) 移除列表中指定位置的元素
public ListIterator listIterator() 返回此列表元素的列表迭代器
remove(Object obj) 如果obj存在则直接移除
remove(int index) 移除指定位置处的元素 并将元素返回给调用者

ArrayList

使用数组结构实现的List集合
在这里插入图片描述
优点:

  • 对于使用索引取出元素有较好的效率
  • 它使用索引来快速定位对象

缺点:

  • 元素做删除或插入速度较慢
  • 因为使用了数组,需要移动后面的元素以调整索引顺序、

LinkedList

LinkedList是使用双向链表实现的集合。

LinkedList新增了一些插入、删除的方法。
在这里插入图片描述
优点:

  • 对频繁的插入或删除元素有较高的效率
  • 适合实现栈(Stack)和队列(Queue)

缺点:

  • 读取数据只能某一方向依次遍历查找 效率较低

Map

在集合中,Map和Collection是一个并列的关系,它内部职能存储键值对(key-value)。且key的值不能重 复且是无序的,value无要求。

JDK API中Map接口的实现类常用的有:

  • HashMap 内部使用哈希表对 “键-值”映射对 进行散列存放。

    ​ 1.使用频率最高的一个集合。

  • LinkedHashMap 是HashMap的子类

    ​ 1.使用哈希表存放映射对

    ​ 2.用链表记录映射对的插入顺序。

Map实现类中存储的“键-值”映射对是通过键来唯一标识,Map底层的“键”是用Set来存放的。 所以,存入Map中的映射对的“键”对应的类必须重写hashcode()和equals()方法。常用String作为Map 的“键”。

Map接口常用方法:

Object put(Object key, Object value); //将指定的“键-值”对存入Map中Object get(Object key); //返回指定键所映射的值Object remove(Object key); //根据指定的键把此“键-值”对从Map中移除。boolean containsKey(Object key); //判断此Map是否包含指定键的“键-值”对。boolean containsValue(Object value); //判断是否包含指定值的“键-值”对。boolean isEmpty(); //判断此Map中是否有元素。方法名 方法介绍
public E push(E item) 把元素压入堆栈顶部
public E pop() 移除堆栈顶部的对象,并作为此方法的值返回该对象
public E peek() 查看堆栈顶部的对象,但不从堆栈中移除它。
public boolean empty() 测试堆栈是否为空。
public int search(Object o) 返回对象在堆栈中的位置,以1为基数。
•int size(); //获得些Map中“键-值”对的数量。void clear(); //清空Map中的所有“键-值”对。Set keySet(); //返回此Map中包含的键的Set集。Collection values(); //返回此Map中包含的值的Collection集。Set<Map.Entry<K,V>> entrySet(); //返回此Map中包含的“键-值”对的Set集

遗留类

Vector

旧版的ArrayList,它大多数操作跟ArrayList相同,区别之处在于Vector是线程同步的。

它有一枚举方式可以类似Iterator进行遍历访问,也可以使用forEach或者Enumcation(JDK1.0用来遍历 集合,后面不推荐使用可以用Iterator替代)

Stack

•Stack类是Vector的子类,它是以后进先出(LIFO)方式存储元素的栈。线程同步的。

Stack类中增加了5个方法对Vector类进行了扩展

方法名方法介绍
public E push(E item)把元素压入堆栈顶部
public E pop()移除堆栈顶部的对象,并作为此方法的值返回该对象
public E peek()查看堆栈顶部的对象,但不从堆栈中移除它。
public boolean empty()测试堆栈是否为空。
public int search(Object o)返回对象在堆栈中的位置,以1为基数。

Hashtable

旧版的HashMap,JDK1.0中创建的,在JDK2.0中使用HashMap替换Hashtable,本身具有线程同步的 功能。

使用方式和HashMap大致一样。

Properties

Hashtable的一个子类,用于获取当前项目中的配置文件中的信息,该类没有泛型 所有的key-value均 为String类型

Properties类表示了一个持久的属性集。Properties可保存在流中或从流中加载。属性集中每个键及其 对应值都是一个字符串。

不建议使用 put 和 putAll 这类存放元素方法,应该使用 setProperty(String key, String value)方法,因 为存放的“键-值”对都是字符串。类似取值也应该使用getProperty(String key)。

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class PropertiesTest {
public static void main(String[] args) {
InputStream is = Thread.currentThread()
	.getContextClassLoader()
	.getResourceAsStream("config.properties");
Properties prop = new Properties();
	try {
prop.load(is);
	} catch (IOException e) { e.printStackTrace(); }
String name = prop.getProperty("name");
String pwd = prop.getProperty("pwd");
System.out.println(name + ", " + pwd);
	}
}

排序接口

TreeSet & TreeMap

在集合中存在一个自动排序的存储集合,底层使用红黑树进行数据存储。

只要存入该集合中的数据都会按照排序规则进行默认排列

对于数据类型的包装类 以及 String类型 默认都实现了排序接口 会按照字典顺序进行数据排列

如果希望元素放置在TreeSet或者TreeMap中 则该对象必须实现比较接口Comparable 否则在存放时会 抛出异常

Comparable

比较接口,所有需要实现排序规则的对象都应该实现该接口,表示该类时一个可比较类。

实现Comparable时需要实现其CompareTo(Object o) 方法

按照升序进行判定规则:

a.age > b.age 需返回 正整数

a.age < b.age 需返回 负整数

a.age == b.age 需返回 0

按照降序排列则只需将正整数和负整数的位置交换即可

优点:无序另外设置排序规则,在可排序的方法中可以直接进行排序

缺点:在一个项目中如果实现Comparable 则该对象默认只能有一种排序方式

public class Student implements Comparable{
    private int id; //编号
    private String name; //姓名
    private double score; //考试得分
    public Student(){}
    public Student(int id, String name, double score) {
        this.id = id; this.name = name; this.score = score;
    }
    //省略所有属性的getter和setter方法
    //实现compareTo方法,按成绩升序排序
    public int compareTo(Object o) {
        Student other = (Student)o;
        if(this.score > other.score){ return 1;
                                    }else if(this.score < other.score){ return -1;
                                                                      }else{ return 0; }
    }
    public boolean equals(Object obj) {}
    public int hashCode() {}
}

Comparator

比较器接口,可以自定义一个类来实现Comparator接口,并实现其compare(Object o1,Object o2)方 法

比较规则和Comparable中的规则一致。

优点:在一个项目中可以按照不同的需求定义不同的比较器,在具体需求出使用精准的比较规则来进行 数据排序

缺点:在使用时需要手动告知排序接口排序规则(设置参数),如果仅使用一次则见识使用匿名内部类 或Lambda表达式来实现

当一个对象即实现了Comparable接口 用有Comparator类型的排序类 则如果显示调用Comparator的 排序类 会覆盖Comparable的实现规则 否则直接使用Comparable的默认排序

/** 学生考试得分比较器 */
class StudentScoreComparator implements Comparator<Student>{
    public int compare(Student o1, Student o2) {
        if(o1.getScore() > o2.getScore()){ return 1;
                                         }else if(o1.getScore() < o2.getScore()){ return -1;
                                                                                }else{ return 0; }
    }
}
/** 学生姓名比较器 */
class StudentNameComparator implements Comparator<Student>{
    public int compare(Student o1, Student o2) {
        return o1.getName().compareTo(o2.getName());
    }
}
//使用不同比较器的排序集合
Set<Student> set = new TreeSet<Student>(new StudentScoreComparator());
Set<Student> set2 = new TreeSet<Student>(new StudentNameComparator());

Collections

针对于集合专门设计的工具类,提供了集合常用的功能,方便开发者提升开发效率。

常用方法:

void sort(List list) 根据元素的自然顺序 对指定List列表按升序进行排序。List列表中的所有元素都必
须实现 Comparable 接口。
void shuffle(List list)List列表内的元素进行随机排列
void reverse(List list)List列表内的元素进行反转
void copy(List dest, List src) 将src列表内的元素复制到dest列表中
List synchronizedList(List list) 返回指定列表支持的同步(线程安全的)列表

集合类的线程安全

集合类大多数默认都没有考虑线程安全问题,程序必须自行实现同步以确保共享数据在多线程下存取不 会出错:

使用同步锁

  • synchronized(list){ list.add(…); }

用java.uitl.Collections的synchronizedXxx()方法来返回一个同步化的容器对象

•List list = Collections.synchronizedList(new ArrayList());

这种方式在迭代时仍要用synchronized修饰

List list = Collections.synchronizedList(new ArrayList());
...
    synchronized(list) {
    Iterator i = list.iterator();while (i.hasNext()) {
        foo(i.next());
    }
}

从JDK5.0开始,提供了一个concurrent包,专门提供了一些在并发操作中好用的对象。跟集合相关的常 用对象有:

  • ConcurrentHashMap
  • CopyOnWriteArrayList
  • CopyOnWriteArraySet

以上的对象在同步性和效率性上进行了平衡,只在修改元素时加锁,在读取元素时不上锁,提高读取效 率,适合使用于并发性强且不长修改的数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

于歌852

您的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值