JAVA中的容器总结

1 容器概念

1.1 容器是什么

在Java当中,如果有一个类专门用来存放其它类的对象,这个类就叫做容器
是将若干性质相同或相近的类对象组合在一起而形成的一个整体

1.2 容器和数组的区别和联系

1.2.1 区别

1.2.1.1 为什么需要容器

1 数组的长度难以扩充
2 数组中数据的类型必须相同
3 数组只能创建固定长度的对象

1.2.1.2 容器和数组的操作区别

容器不是数组,不能通过下标的方式访问容器中的元素

1.2.2 联系


1 数组的所有功能通过Arraylist容器都可以实现,只是实现的方式不同
2 如果非要将容器当做一个数组来使用,通过toArraylist方法返回的就是一个数组

1.2.3 数组Arrays类常用方法总结

  • 排序相关
 public static void sort(int[] a);
 //从小到大排序
 public static void sort(int[] a, int fromIndex, int toIndex);
 //从哪个元素到哪个元素排序,[fromIndex,toIndex),不包括toIndex
 public static void parallelSort(int[] a);
 public static void parallelSort(int[] a, int fromIndex, int toIndex);
 //1.8之后对排序做的优化

//Object[] 数组的排序有些不同
public static void sort(Object[] a);
private static void legacyMergeSort(Object[] a);
//object[]的sort调用的下面的legacyMergeSort,采用的是插入排序,注意legacyMergeSort是private的,外部不能调用
  • 二分法
public static int binarySearch(int[] a, int key);
public static int binarySearch(int[] a, int fromIndex, int toIndex,int key);
//注意,Java中个给的二分,只是说这段区间中有没有,并返回该index,而不是返回第一个出现的位置或者是最后一次出现的位置
//使用二分搜索法搜索指定列表,以获得指定对象。在进行此调用之前,必须根据列表元素的自然顺序对列表进行升序排序(通过 sort方法)
//如果没有对列表进行排序,则结果是不确定的。如果列表包含多个等于指定对象的元素,则无法保证找到的是哪一个。  

//[1] 该搜索键在范围内,但不是数组元素,由0开始计数,得“ - 插入点索引值 -1”;举例搜索3,数组[1 2 4]
//插入点是指第一个大于该键key的元素的索引。
//[2] 该搜索键在范围内,且是数组元素,由0开始计数,得搜索值的索引值;搜索3 数组[1 2 3]
//[3] 该搜索键不在范围内,且小于范围(数组)内元素,返回–fromIndex - 1;搜索0 数组[1 2 3]
//[4] 该搜索键不在范围内,且大于范围(数组)内元素,返回 –toIndex - 1。搜索4 数组[1 2 3]

//运用的时候,一般判断是否大于0
  • 其他常用
public static boolean equals(int[] a, int[] a2);
//判断两个数组元素是否相等

public static void fill(int[] a, int val);
public static void fill(int[] a, int fromIndex, int toIndex, int val);
//用val填充数组

public static int[] copyOf(int[] original, int newLength);
//将原数组拷贝到一个长度为newLength的新数组中,并返回该数组,newLength较大就用0填充,小就截取前一部分
public static int[] copyOfRange(int[] original, int from, int to);
//返回一个从from到to复制的一个数组,length=to-from

public static int hashCode(int a[]);
//返回hashcode
public static String toString(int[] a);
//Arrays.toString(a)非常方便打印数组元素

public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }
//Arrays.asList把数组元素填充到一个List返回

2 容器总结

2.1 容器接口及分类

这里写图片描述
大方向上,主要分为Iterator、Collection、Map、Comparable四大接口

其中Iterator迭代器,设计的目的是在未知容器具体的类型的情况下,用来遍历容器元素,与foreach一起使用

Comparable接口则用于比较

剩下的容器类型都是继承了Collection、Map接口
具体划分下,List、Set、Queue接口继承Collection接口

2.2 Collection、Map接口方法分析

2.2.1 Collection接口

序列容器,保存单一的元素

·collection接口的定义方法

向上转型定义

ArrayList list = new ArrayList();
//普通定义了一个ArrayList类对象

List list = new ArrayList();
Collection con = new ArrayList();
//向上转型到List或者collection接口
//向上转型到哪个接口看自己情况,但是new的一定是类,接口是不能new的!!!!!

List<Integer> = new ArrayList<>();
//加了泛型
List<List<Integer>> list = new ArrayList<>();
//List嵌套List的定义new的也是一个ArrayList

//初始化
List<Integer> objList = new ArrayList(Arrays.asList(new Integer[]{1,2,3}));
List<Integer> objList = Arrays.asList(new Integer[]{1,2,3});
·collection接口的遍历方法
//方法一:
//超级for循环遍历
for(String attribute : list) {
  System.out.println(attribute);
}
//方法二:
//对于ArrayList来说速度比较快, 用for循环, 以size为条件遍历:
for(int i = 0 ; i < list.size() ; i++) {
  system.out.println(list.get(i));
}

//方法三:
//集合类的通用遍历方式, 从很早的版本就有, 用迭代器迭代
Iterator it = list.iterator();
while(it.hasNext()) {
  System.ou.println(it.next);
}
·collection接口的常见方法

1 单元素的操作

boolean add(Object o);
//将对象添加给集合
//集合调用add方法发生改变则返回true
boolean remove(Object o);
//删除集合中的某一元素
//删除成功返回true
boolean contains(Object o);
//查找集合中是否含有元素o
boolean equals(Object o);

2 一个集合的操作

boolean addAll(Collection c);
//添加集合C元素到当前集合
//如果集合调用addAll方法而发生更改返回true
//参数c用于指定要将全部元素添加到列表中的collection
boolean removeAll(Collection c);
//从集合中删除集合c中的所有元素
//如果集合调用removeAll方法而发生更改返回true
boolean retainAll(Collection c);
//从集合中删除集合c中不包含的元素
//如果集合调用方法而发生更改返回true
boolean containsAll(Collection c);
//查找集合中是否含有集合c中的所有元素
//全部包含返回true

3 查询操作

void clear();
//清空集合
int size();
//返回集合元素个数
int hashCode();
//返回集合的hashcode
boolean isEmpty();
//判断当前集合是否为空,空为true
Iterator<E> iterator();
//返回一个迭代器,用来访问集合中的各个元素

4 和数组之间的转化

 Object[] toArray();
 //返回一个内含集合所有元素的数组
 //无需传入参数,可以直接将集合转换成Object数组进行返回,而且也只能返回Object类型

//还有一个重载方法
<T> T[] toArray(T[] a);
//同样返回一个内含集合所有元素的数组
//需要传入一个数组作为参数,并通过泛型T的方式定义参数,所返回的数组类型就是调用集合的泛型,所以自己无需再转型
//但是根据传入数组的长度与集合的实际长度的关系,会有不同的处理
//a:数组长度不小于集合长度,直接拷贝,不会产生新的数组对象;
//b:数组长度小于集合长度,会创建一个与集合长度相同的新数组,将集合的数据拷贝到新数组并将新数组的引用返回。
collection.add(Arrays.asList(array));
//将数组添加到collection中,这里返回的是ArrayList
//Arrays.asList方法
//这里是将整个数组作为collection的一个元素添加进去的

//如果要将数组内的元素作为collection的相互独立的元素添加,就是直接asList()
//但是需要注意的是, Arrays.asList() 返回一个受指定数组决定的固定大小的列表。所以不能做 add 、 remove 等操作,否则会报错。
//或者在定义的时候转换添加
Collection con = new ArrayList(Arrays.asList(array));
·collection接口的分类
  • 1 List接口
    类似于数组,创建数字索引和对象的关联,能够自动扩充容量
    • ArrayList
      类似于动态数组,适用于大量随机访问
      的情况,但插入和删除的代价非常高昂
    • LinkedList
      类似于链表,也提供了优化的顺序访问,在表中间插入和删除方面代价低廉,随机访问代价较高
      添加了可以使其作为栈、队列、双端队列的方法
  • 2 Set接口
    Set不保存重复的元素,Set具有和Collection完全一样的接口,没有额外的功能

    • HashSet
      提供最快的查询速度

    • TreeSet
      保持元素处于排序状态

    • LinkedHashSet
      以插入顺序保存元素

  • 3 Queue接口
    队列是一个典型先进先出(FIFO)的容器,从容器的一端放入事物,从另一端取出,并且事物放入容器的顺序和取出的顺序是相同的。
    队列常被当做一种可靠地将对象从程序的某个区域传入到另一个区域的途径,在并发编程中极为重要。

    • LinkedList
      典型队列
    • PriorityQueue
      优先级队列
      与普通队列不同,优先队列每次弹出的是优先级最高的元素。可以通过提供自己的Comparator来修改
·collection接口内部的互相转换(包括数组)
//List 转 数组
Object[] result = List.toArray();

//数组 转 Set
Set staffsSet = new HashSet(Arrays.asList(array));
//Set 转 数组
Object[] result = Set.toArray();
//List 转 Set
Set result = new HashSet(List);
//Set 转 List
List result = new ArrayList(set);


所以你看,collection下都可以之间转化,和数组之间也都是依赖于toArray()和asList(),但是这里面asList()有一些必须要注意的地方

·asList()方法的一些坑 (重要)

首先我们来看asList()方法的源码

    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

这里返回的ArrayList并不是我们上面collection接口下的ArrayList,而是在Arrays类内定义的一个静态内部类

private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable

同样需要注意的就是asList方法传入的参数是泛型T的一个参数a,这个a是类为T的一个对象,是的没有错这里要求是一个*类对象*

那将意味着对于基本数据类型int float char这些构成的数组int[]只能作为一个类对象处理
原因:int[]数组内的元素是int,是基本数据类型,而不是类,但是int[] 是一个类,所以a变量作为类参数传递时,编译器认为只传了一个变量,这个变量的类型是int数组,所以size为1
但是对于Integer[]来讲,里面每一个元素都是Integer类变量,故每一个元素都能作为list的一个元素

我们看一下对比

int[] i={11,22,33};  
List intList = new ArrayList(Arrays.asList(i));  
//intList中就有一个Integer数组类型的对象,整个数组作为一个元素存进去的    
Integer[] ob={11,22,33};  
List<Integer> objList = new ArrayList(Arrays.asList(ob)); 
//数组里的每一个元素都是作为list中的一个元素  


那么如何直接根据基本类型的数组如int[],long[]直接用asList转成list??
我们可以选择用apache commons-lang工具包里的数组工具类ArrayUtils类的toObject()方法将int[]转换为Integer[],是Apache提供的class,功能呢强大,要注意导包:

//或者 maven
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.5</version>
    </dependency>
    </dependencies>
Arrays.asList(ArrayUtils.toObject(i));
//上边的代码:int i[]={11,22,33};,达到了我们想要的效果  

不能导包的话,就只能自己遍历add了


2.2.2 Map接口

Map是一种将对象和对象相关联的设计

·Map接口的定义方法

和Collection接口一致,向上转型定义

·Map接口的遍历方法
//重要的遍历方法
Set<Map.Entry<K, V>> entrySet();
//这个方法返回的是一个Set<Map.Entry<K,V>>,用于遍历
for (Map.Entry<String, String> entry : map.entrySet()) {  
   System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());  
  }  
//Map.Entry 是Map中的一个接口,他的用途是表示一个映射项(里面有Key和Value),而Set<Map.Entry<K,V>>表示一个映射项的Set。
//Map.Entry里有相应的getKey、getValue、setValue、equals、hashcode方法
·Map接口的常见方法
int size();
//返回map长度大小
boolean isEmpty();
//判断map是否为空,空为true
boolean containsKey(Object key);
//判断map中是否包含key,包含为true
boolean containsValue(Object value);
//判断map中是否包含value,包含为true

V get(Object key);
//取值
V put(K key, V value);
//存值(k,v)+返回值:若k存在在map中返回原先的旧value,若不存在返回null
V remove(Object key);
//删除(k,v)+返回值:若k存在在map中返回原先的旧value,若不存在返回null
Set<K> keySet();
//返回map中所有key,是一个set,没有重复值
Collection<V> values();
//返回map中的所有value,一个collection

void putAll(Map m);
//putAll可以合并两个MAP,只不过如果有相同的key那么用后面的覆盖前面的
void clear();
//清空map

boolean equals(Object o);
//两个map是否相等
int hashCode();
//map的hashCode
·Map接口的分类
  • HashMap
    用来快速访问

  • TreeMap
    保持“键”始终处于排序状态

  • LinkedHashMap
    保持元素插入的顺序,通过散列同样提供了快速访问能力

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值