集合框架的基本操作

一、概述

1、为什么会出现集合类?

面向对象语言对事物的描述都是以对象的形式,为了方便对多个对象的操作,就需要对对象进行存储,集合就是存储对象最常用的一种方式。

2、数组和集合类都是容器,有什么区别呢?

1,数组长度是固定的,集合长度是可变的。
    2,数组可以存储对象,也可以存储基本数据类型,集合只能存储对象。集合可以存储不同类型的对象。

     3、集合体系

collection
|——List 有序(存入的顺序和取出的顺序一致)。有索引。允许重复元素。
| |——LinkedList
| |——ArrayList
| |——Vector
| |——Stack
|——Set 不允许重复元素。
    Map
    |——HashTable------线程安全,低效,不支持null
    |——HashMap--------非线程安全,高效,支持null
    |——WeakHashMap

二Collection接口中的共性功能

    1,添加


boolean add(Object obj); //一次添加一个
boolean addAll(Collection coll); //将指定容器中的所有元素添加到容器中

      2、删除  


void clear(); //
boolean remove(Object obj); //删除此Collection中指定的元素。如果存在。
boolean removeAll(Collection coll); //删除此Collection中所有包含在指定Collection中的所有元素。
boolean retainAll(Collection coll); c1.retainAll(c2);   将c1和c2不同的元素从c1中删除,保留c1中和c2中相同的元素。


    3,获取长度


int size();

    4,判断

boolean isEmpty(); //判断集合是否为空
boolean contains(Object obj); //判断集合中是否包含此对象
boolean containsAll(Collection coll); //如果此Collection包含指定Collection中的所有元素,则返回true
   

5,将集合转换成数组


toArray()
toArray([])
    

6,取出集合元素   

Iterator iterator()
获取集合中元素上迭代功能的迭代器对象
迭代:取出元素的一种方式。有没有?有!取一个。还有没有?有!取一个。还有没有?没有!算了。
迭代器:具备着迭代功能的对象。
而迭代器对象不需要new 。直接通过iterator()方法获取即可


迭代器是取出Collection集合中元素的公共方式。


7,Iterator迭代器包含的方法   


hasNext() 如果迭代器指向位置后面还有元素,则返回true,否则返回false
next() 返回集合中Iterator指向位置后面的元素,同时迭代器指向位置后移
remove() 删除集合中Iterator指向位置后面的元素
    

8,List接口中的特有方法:它的特有方法都是围绕索引定义的   


    增:
add(index,element);


    删:
remove(index);
    
    改:
set(index,element);
    
    查:
int indexOf(element);
element get(index);


    9,List集合特有的取出方式


for(int i = 0; i<list.size();i++){
list.get(i);
}


for(Iterator it = list.iterator();it.hasNext();){
it.next();
}




    ListIterator是List集合的特有的迭代器,通过List集合的方法listIterator()获取该迭代器对象。
    ListIterator可以实现迭代过程中的增删改查

10,解决在遍历过程中要对集合进行操作产生异常的问题


由于迭代过程中使用了集合对象同时对元素进行操作,导致迭代的不确定性,引发了该异常。(java.util.ConcurrentModificatException)
解决思想:在迭代的过程中,想要执行一些操作,使用迭代器的方法就可以了。


for(ListIterator it = list.listIterator();it.hasNext();){
Object obj = it.next();
if(obj.equals("")){
it.add("");
}
}



三、List集合的使用

1,List集合的常用子类

List集合的具体子类,子类之所以区分是因为内部的数据结构(存储数据方式)不同
   |--Vector 数据结构是数组,数组是可变长度的(不断new新数组并将原数组元素复制到新数组中)。线程是同步的。无论增删还是查询,都慢。
   |--ArrayList 也是数组结构,也是长度可变的。线程不同步,替代了vector,增删速度不快,查询速度很快(在内存中连续存储)
   |--LinkedList 链表结构,线程不同步的,增删速度快。查询速度较慢。


2、使用ArrayList去除集合中的重复元素。

方式一:

 <span style="white-space:pre">	</span>public static void singleElement(){
		for(int x = 0;x = list.size()-1;x++){
		    Object obj_x = list.get(x);
		    for(int y = x + 1;y=list.size();y++){
			if(obj_x.equals(list.get(y))){
			    list.remove(y);
			    y--;
			}
		    }
		}
	    }
方式二:


思路:
		1,最后唯一性的元素也很多,可以先定义一个容器用于存储这些唯一性的元素
		2,对原有容器进行元素获取,并到临时容器中判断是否存在。容器本身就有这个功能,判断元素是否存在
		3,如果存在就不存储,如果不存在就存储。
		4,遍历完原容器后,临时容器中存储的就是唯一性元素。

		public static void singleElement(List list){
		    //定义一个临时容器
		    List temp = new ArrayList();
		    //2,遍历原容器
		    for(Iterator it = list.iterator();it.hasNext();){
			Object obj = (Object)it.next();
			//3,在临时容器中判断遍历到的元素是否存在。
			if(!temp.contains(obj)){
			    //4,如果不存在,就存储到临时容器中
			    temp.add(obj);
			}
		    }

		    //5,将原容器清空
		    list.clear();
		    //6,将临时容器中的元素都存储到原容器中
		    list.add(temp);

		}

3,LinkedList特殊的方法

   添加方法:
addFirst(); 将指定元素插入到此列表的开头
addLast(); 将指定元素添加到此列表的结尾
   获取元素:
getFirst(); 返回列表的第一个元素。
getLast(); 返回列表的最后一个元素。
   删除元素:
removeFirst(); 移除并返回此列表的第一个元素。
removeLast(); 移除并返回此列表的最后一个元素。




四、Set集合的使用

Set集合:不允许重复元素,和Collection的方法相同 ,Set 集合取出方法只有一个:迭代器
   |--HashSet 哈希表(散列)结构,
   |--TreeSet 可以对元素进行排序

1,存储原理:

set集合存储元素时,经过Hash算法计算Hash值,然后根据hash值把元素存储到特定的位置。查询时,计算hash值,根据hash值查询元素。


2,元素为什么是唯一的:

不允许存储重复元素,防止发生查找的不确定性。
   不保证存入和取出的顺序一致


3,特点:

比数组的查询效率高

 4,相关概念:

   1、 用于存储元素和哈希值对应关系的容器称之为哈希表


   2、Hash冲突
当哈希算法算出两个元素的值相同时,称为哈希冲突
冲突后,需要对元素进行进一步的判断,判断的是元素的内容,equals进行判断 


哈希表在判断元素是否相同:依据hashCode()方法,如果哈希值冲突(哈希值相同),再判断元素的equals方法。如果equals返回true,不存储,返回false,存储。


5,set集合存储自定义的对象时,如何保证唯一性。

   元素必须覆盖hashCode和equals方法
   覆盖hashCode方法是为了根据元素自身特点确定哈希值。
   覆盖equals方法是为了解决哈希值的冲突



、Map集合的使用

Map:双列集合,一次存一对,键值对,要保证键的唯一性。

        1、共性的功能


   1,添加
V put(K key,V value); //如果键值对时,如果键相同,会出现值覆盖。 返回值:与key关联的旧值;如果key没有任何映射关系,则返回null
putAll(Map<k,v> map);
   2,删除
void clear();
V remove(K key); //返回被删除key关联的value 获取的同时删除
   3,判断
boolean containsKey(Object obj);
boolean containsValue(Object obj);
boolean isEmpty();
   4,获取
V get(K key); //根据键获取对应的值
int size();

   5、获取所有
Collection<V> values(); //返回此映射中包含的值的Colleciton视图
Set<K> keySet(); //返回此映射中包含的键的Set视图
Set<Map.Entry<K,V>> entrySet(); //返回此映射中包含的映射关系的Set视图
   


    2、如何取出Map中所有的元素。

1、keyset() 返回所有的键
Map集合没有迭代器。但是可以将Map集合转成Set集合,再使用迭代器进行迭代获取。


Set<K> keyset() //取出所有的键,并存储到set集合中 因为Map中键具有唯一性,所以set集合
流程:
   Map---->keyset()------>Set<Key>------>iterator------>map.get(key);


代码:
   Set<String> keySet = map.keySet();
   for(Iterator<String> it = keySet.iterator();it.hasNext();){
String key = it.next();
String value = map.get(key);
   }


2、entrySet() //返回所有的键值对(此映射中包含的映射关系的set视图)
   Map.Entry:其实就是Map接口中的一个内部接口,
   流程:
map ---->entrySet()----->Set<Map.Entry<>>---->iterator-----Map.Entry<>---->getKey();getValue();
   代码:
   Set<Map.Entry<String,String> entrySet = map.entrySet();
   for(Iterator<Map.Entry<String,String>> it = entrySet.iterator();it.hasNext()){
Map.Entry<String,String> me = it.next();
String key = me.getKey();
String value = me.getValue();
   }




    3、Map集合的常见子类

|--HashTable: 哈希表,是同步的,不允许null键和null值
   |--LinkedHashMap:保留插入的顺序,如果需要输出的顺序和输入时的相同,就选用LinkedHashMap
|--HashMap: 哈希表,是不同步的,允许null键和null值
|--TreeMap: 二叉树,是不同步的,可以对Map集合中的键进行排序




    4、Map集合的应用 

当需求中出现映射关系时,就应该最先想到Map集合




    5、Map集合Demo

需求:获取字符串中每一个字母出现的次数,要求格式:a(2)b(1)d(3).....
思路:
   1,获取字符串中的字母
   2,获取字母次数
字母和次数有对应关系,而且对应关系的一方具备唯一性。
使用Map集合,Map集合实际上就是一张表。
   3,使用查表法
先查第一个字母在表中的次数,如果次数不存在,说明是第一次出现,将该字母和1存储到表中
依次类推。当要查询的字母次数存在,将次数取出自增后,再和对应的字母存储到表中,map的特点是键相同,值会被覆盖。
   4,查完每一个字母后,表中存储的就是每一个字母出现的次数。




代码:
   String str = "";
   String charCount = getCharCount(str);
   public static String getCharCount(String str){
//1,将字符串转成字符数组
char[] chs = str.toCharArray();
//2,定义map集合
Map<Character,Integer> map = new TreeMap<Character,Integer>();
//记录次数
int count = 0;
//3,遍历字符数组,获取每一个字母
for(int i = 0;i < chs.length;i++){
   //将遍历到的字母作为键去查表,获取值。
   Integer value = map.get(chs[i]);
   //如果次数存在,就用count记录该次数,如果次数不存在,就不记录,只对count进行自增。
   if(value!=null){
count++;
   }
   count++;
   map.put(chs[i],count);


}
   }

六、Arrays,操作数组的工具类

1、常用方法

   1,复制数组
copyOf(original,newLength) 返回原数组的副本,截取或用0填充以获得指定的长度。 original:要复制的数组 newLength:要返回副本的长度
public static byte[] copyOf(byte[] original,int length)
   2,数组是否相等
equals(a1,a2) 如果两个数组相等,则返回true


   3,填充数组
fill(a,val) a:要填充的数组 val:要存储在数组所有元素中的值。
public static void fill(int[] a,int val) 将指定的 int 值分配给指定 int 型数组的每个元素。


   4,排序
sort(a) 参数:a要排序的数组
   5,格式为字符串形式。
toString(a) 返回a的字符串表示形式 参数a - 返回其字符串表示形式的数组 

2、数组和集合的相关转换

1、数组转成集合

原因:为了使用集合的方法操作数组中的元素。


Arrays.asList(a); 返回一个受指定数组支持的 固定大小 的列表 参数a 数组


注意:
    1,如果数组中都是引用数据类型,转成集合时,数组元素直接作为集合元素。
      如果数组中都是基本数据类型,会将数组对象作为集合中的元素。


java.lang.UnsupportedOperationException
不能使用集合的增删方法,因为是固定大小的列表,所以不能改变长度。




int[] arr = {45,27,78,15,99}; 基本数据类型
List<int[]> list = Arrays.asList(arr);
list.get(0); 地址值

Integer[] arr = {45,27,78,15,99}; 引用数据类型
List<Integer> list = Arrays.asList(arr);
list.get(0); 45


    2、集合转成数组
原因:就是为了限定对元素的操作,比如增删
Collection中的toArray方法
List<T> list = new ArrayList<T>();
list.add();
list.add();
T[] arr = list.toArray(new T[list.size()]);


注意:
    传入的数组的长度,如果小于集合的长度,方法中会创建一个新的数组,新数组的长度和集合的长度一致。
    如果传入的数组长度大于等于集合长度,会使用方法中传入的数组。所以建议长度定义为集合的size

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值