⼀⽂讲清java中的集合使⽤⽅法
⼀. java中为什么会产⽣容器(集合)这个概念:
1.集合是什么以及要学习集合的什么?
集合的本质是java API(java固有的)中提供的⼀系列类的实例,⽤于在程序中存放对象.⽽且这些类中有很多实⽤的⽅法可以让使⽤者⽅便的处理这些集合.集合分成很多种类型,不同类型的集合具有不同的特点,不同的使⽤场景和不同的内存存储⽅式.所以学习集合完之后要知道处理问题时该定义哪种集合,怎么调⽤该集合的⽅法甚⾄于该怎么⾃⼰去实现这个集合以及它的⽅法.
2.有数组了,为什么还要有集合?
数组可以存对象也具有⼀些处理对象的⽅法为什么还需要集合?从两者的特点来看看:
聊聊数组的特点:
内部的所有元素类型都是⼀致的;
数组定义之后的长度是固定的(所以数组长度的变化⼀般是定义⼀个新的数组把old->new,然后追加);
数组内部的元素类型可以是基本数据类型也可以是类.
在使⽤过程之中如果需要包含的数据类型不⼀致,或者元素数量不固定.会导致有的元素⽆法加⼊数组或初始分配数组长度不合适(过短不够⽤,过长浪费内存,⽽且需求时常变化难以寻到长度标准);
聊聊集合的特点:
⽽集合只能存储类(集合内部是对象的引⽤,但可是基本类型的包装类),⽽且⼀个集合可存储不同类的类型;
集合可以任意的添加删除元素,并且实时⾃动分配或者释放内存(即使内部⽤数组实现的也会⾃动,不⽤⿇烦使⽤者⾃⼰实现);
集合的类型很多,不同类型的集合适⽤于解决不同的问题,可以使得⼤⼑剁⾁⼩⼑削⽔果,⽽且其丰富的⽅法为使⽤者直接调⽤去"为所欲为".
由上⾯可知在处理⼤量对象时候使⽤集合的意义,也就是java中出现集合概念的意义:
对象⽤于封装特有数据,对象多了需要存储,如果对象的个数不确定就是⽤集合容器进⾏存储.
数量任意 + 使⽤灵活 + ⽅法便捷.
以及各类集合的特点:
集合的组织框架以及各类集合的特点
⼆.集合的
1.集合的组织框架图:
图1. 集合的组织框架图
图1说明:
蓝⾊的集合Collection中是⼀个⼀个的元素,橙⾊集合Map中的是⼀对⼀对的元素(键值对).⿊⾊的是迭代器⽤于遍历集合.
Set中的元素⽆序不可重复,List的元素有序可以重复(重复的标准是两个对象的equals⽅法返回为true, ==:是引⽤相等,不改写equals时
候,==和该⽅法都是表明同⼀个对象才返回true,有序是按照存⼊的顺序).
接⼝:Collection,Set,List,Map.Iterator(适⽤于Collection),ListIterator(只适⽤于List),其余为类.
注意:所有实现了Collection接⼝的容器类都有⼀个iterator⽅法⽤以返回⼀个实现了Iterator接⼝的对象.
该对象根据Collection具体的集合类型定制了合适的遍历对象,然后返回.
2. 集合的分类及其修饰符:
集合中有接⼝和类两种概念,且是⼀个多重继承的体系结构,⽗类(接⼝)的⽅法被⼦类(接⼝)继承,可以直接使⽤.
Collection接⼝-定义了⼀组存取对象的⽅法,其⼦接⼝Set和List分别定义了存储⽅式,Set中的元素⽆序不重复,List的元素有序可重复.
Map接⼝定义了存储"键(key)-值(value)映射对"的⽅法.Map的键是Set.
Array是数组实现(查快),Linked是⽤链表实现(增删快),Hash是哈希表实现.tree是⼆叉树实现(排序),Linked和Hash经常⼀起出现.set(equals,加上hash就再得重写hashCode()).
List多了⼀类索引操作.Linked多了⼀组⾸尾的操作.
tree与comparable接⼝(实现接⼝重写类的compareTo()),tree与comparator接⼝(实现接⼝重写compare()⽅法.参数形式传⼊treeset构建时候的实参),set与equals()⽅法.hash与hashCode(),Comparable接⼝(对应着对象)与Collection.
注意:关键词与关键词的联系来记忆功能.
三.集合的⽅法:
1.Collection接⼝中定义的⽅法:(接⼝Set和List以及其⼦类都可以使⽤)
增 --增⼀个
--增⼀个集合
删 --删⼀个元素
--删⼀个集合
--删除全部元素
包含--包含⼀个元素
--包含⼀个集合
判断--空
--
获取--长度
注意:集合⽅法的同级性与包含性:参数为Object和Collection
int size();//长度
boolean isEmpty(); //空?
void clear();//清空元素
boolean contains(Object element);//包含参数元素?
boolean add(Object element); //增加元素.
boolean remove(Object element);//移除元素.
Iterator iterator();//返回遍历器(因不同的集合遍历⽅法不同,才会被添加为⽅法).
boolean containsAll(Collection c);//包含参数集合?
boolean addAll(Collection c); //增加c集合中元素.
boolean removeAll(Collection c);//移除参数集合中元素.
boolean retainAll(Collection c);//取交集;
Object[] toArray(); //转化为数组.
2.Iterator接⼝中定义的⽅法:(迭代器)
boolean hasNext();//游标右侧是否还有下⼀个元素
jdk怎么使用Object next();//返回游标右边的元素,并右移游标⼀个位置.
void remove();//删除游标左边的元素,在执⾏完next后该操作只能执⾏⼀次.//该⽅法是在迭代中删除元素的唯⼀的安全的⽅法.
注意:该接⼝在遍历时候,会锁上该集合,是的集合本⾝修改时候会出现异常.
3.Set接⼝中定义的⽅法: (set对equals(),再hash还得hashCode(),TreeSet只看compareTo())
和Collection⼀样,没有⾃⼰添加的⽅法只是添加⼊该集合的对象⼀般重写equals()⽅法,因为相同的元素不会重复存⼊。且本⾝没有按照存⼊的顺序存储。
HashSet内部数据结构是哈希表,是不同步的.(线程不安全的),hash表内部还是数组,但hash算法对数
据进⾏了优化,利⽤参数值带⼊hash算法值获取存储位置.(hashset是先判断哈希值(hashCode),然后判断内容值(equals()),如果哈希值不同是不需要判断equals()).
所以要存⼊hashSet集合的类需要重写equals()和hashCode(),且两类型同⽅法返回的值要⼀致.
LinkedHashSet集合:按存储顺序的.
TreeSet:可以排序的,默认时候按⾃然排序.这个集合只判断对象的compareTo()的值,相等就不加元素认为重复,不相等根据这个排序.
TreeSet集合的第⼆种排序⽅式⼆:让集合⾃⾝具备⽐较功能.
4.List接⼝定义的⽅法:
List中的元素都对应⼀个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
List中元素的顺序默认为存⼊的顺序。
Object get(int index); //获取索引index处的值。
Object set(int index ,Object element); //设置index的值,返回的是⽼的值。
void add(int index ,Object element); //添加⼀个别的往后挤。
Object remove(int indx); //删除指定索引的值。
int indexOf(Obiect o); //获取值为o的第⼀个索引。
int lastIndexOf(Object o);//获取值为o的最后⼀个索引。
下分的ArrayList和LinkedList是底层实现不同,别的使⽤没多少不同,根据作⽤选择使⽤.
4'ListIterator接⼝中的⽅法:(该⽅法只适⽤于List集合)
除了具有Iterator的⽅法(向后)之外还增加了向前的操作,更重要的是增加了以下操作:
add();
set();
注意这两个操作都是对于遍历位置所进⾏的操作.
5.类java.util.Collections提供了⼀些静态⽅法实现了基于List容器的⼀些常⽤算法:
void sort(List);//对List集合内的元素排序。
void sort(list,comparator);//给Collection集合加上⽐较器.
void shuffle(List);//对List容器内的对象进⾏随机排列。
void revervse(List);//对List集合内的元素进⾏逆序排列。
void fill(List ,Object);//⽤⼀个特定的对象重写整个List集合。
void copy(List dest ,List src);//拷贝List集合。
int binarysearch(List , Object);//对于顺序List容器,⽤折半查⽅法查特定对象.
6.Comparable接⼝中定义的⽅法:
java.lang.Comparable接⼝其中只有⼀个⽅法:
public int compareTo(Object obj); //返回0时表⽰this == obj //返回正数表⽰this > obj //返回负数表⽰this < obj.
实现了该接⼝的类通过实现compareTo⽅法从⽽确定该类对象的排序⽅式。java.util.Collections中的排序⽅法使⽤的该接⼝的⽐较器。
6'.Comparator接⼝:(与tree)(⽐较器与上⾯与同时存在就优先这个)
需要覆盖重写⼀种⽅法:compare();
7.Map接⼝中的⽅法:(判断可键可值,操作⼀般是键)
实现Map接⼝的类⽤来存储键-值对。
Map接⼝的实现类有HashMap和TreeMap等.
Map类中存储的键-值对,通过键来标识,所以键值不能重复。键值必须重写equals()和hashcode(),且⼀致。
Map集合必须保持键的唯⼀性.
Object put(Object key,Object value);//可添加可修改.
Object get(Object key);//由键获取值.没有返回null.
Object remove(Object key);//删除指定键值对.
boolean containsKey(Object key);//是否包含指定的键.
boolean containsValue(Object value);//是否包含指定的值.
int size();//集合的⼤⼩.
boolean isEmpty();//判断是否为空.
void putAll(Map t);//将⼀个Map类中所有键值对添加进另⼀个Map中.
void clear();//清空map集合.
Set<K> keySet();//返回此映射中所包含的键的Set视图.
Set<Map.Entry<K,V>> entrySet(); //返回该映射所包含的映射关系的Set视图.
Collection<V>values();//返回该映射所包含的collection视图.
7'.Map.Entry<K,V>(Map集合接⼝的内部接⼝)中的⽅法:(存的是Map中的结婚证,在遍历时候使⽤)
K getKey();
V getValue();
V setKey();/setValue();
Map集合的迭代⽅法:
(1)第⼀种⽅法原理:通过keySet()⽅法获取map中所有的键所在的Set集合,再通过Set的迭代器获取到每⼀个键.,再对每⼀个键获取其对应的值即可.
Set<Integer> keySet = map.keySet();
Iterator<Integer> it = keySet.iterator();
while(it.hasNext()){
Interger key = it.next();
System.out.println(key);
String value = (key);
}
(2)第⼆种⽅法:通过Map转化为set就可以迭代,到了另⼀个⽅法.entrySet:该⽅法将键和值的映射对象存储在了Set集合中,⽽这个映射关系的类型就是Map.Entry类型(结婚证).
Set<Map.Entry<Integer,String>> entrySet = Set();
Iterator<Map.Entry<Integer,String>> it = entrySet.iterator();
while(it.hasNext()){
Map.Entry<Integer,String>me = it.next(); //Map.Entry<Integer,String>该类⽅法有很多
Integer key = me.getKey();
String value = me.getValue();
String value = (key);
}
11381:个图( 集合框架图),1个类( Collections类(⼯具类)),3个知识点(for,Generic(fan),⾃动装包,解包),7个接⼝( Iterator接⼝(collection),ListIterator接⼝(List),Comparable接⼝(Tree中存的对象实现),Comparator接⼝(tree集合参数),Collection接⼝,Set接⼝(⽆序),List接⼝(有序),Map接⼝).
四.集合的附属-泛型
1.泛型的作⽤:
jdk1.5出现的安全机制,将运⾏时期的问题ClassCastException异常转化到编译时期.程序员可以去解决了.
避免了强制转化的⿇烦.
2.泛型的使⽤:
(1)什么时候⽤?
当操作的引⽤数据类型不确定的时候,就使⽤<>.将要操作的引⽤类型传⼊即可.<>本质就是⽤来接收具体引⽤数据类型的参 数范围.在程序中只要是带有<>就需要明确传⼊的数据类型.
泛型技术是给编译器使⽤的技术,⽤于编译时期,确保了类型的安全.
运⾏时,会将泛型去掉,⽣成的class⽂件中不带泛型,这个称为泛型的擦除.
(2)泛型使⽤的表现形式:
泛型与集合
集合新定义前后都需要泛型,接⼝实现只后⾯泛型.基本上属于 使⽤传⼊即可.
泛型与类
⾃⼰ 定义时候:
public class Tool<T>{
//⾥⾯就可以使⽤T这个类型来定义
}
当类中的操作的引⽤数据类型不确定的时候,就使⽤泛型来表⽰.
使⽤时候:
Tool<Student>tool = new Tool<Student>();
之后不⽤强制类型转换.
泛型与接⼝
⾃⼰ 定义时候:
interface Inter<T>{
public void show(T t);
}
实现时候:
class InterImpl implements Inter<String>{
public void show(String t);
}
使⽤时候和平常⼀样.
InterImpl in = new InterImpl();
in.show("abc");
后两步或者:
实现时候:
class InterImpl2 <Q>implements Inter<Q><String>{
public void show(Q t){
//实现⽅法;
}
}
使⽤时候:
InterImpl<String> in = new InterImpl<String>();
in.show("abc");
泛型与⽅法:在返回值前
⾮静态⽅法:
⾃⼰定义时候:
public <w> void show(w str){
//对str操作;
}
使⽤时候:
tool.show("abc");//使⽤时候直接传对象就可以了,不⽤额外的操作.
或者借助类的泛型来定义,但是使⽤时候只能是类的泛型类型.
注意: 静态⽅法是不能访问类上定义的泛型,因为泛型依赖于对象,只能采⽤这种⽅法将泛型定义在⽅法上.
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论