集合的作用
用于存储多个同一类型的元素。
集合的分类
集合可以分为单列集合和双列集合。
单列集合的一个元素只由一部分组成,所使用的是Collection接口;而在Collection接口下还有两个子接口:
- List接口
- Set接口
双列集合的一个元素由K、V两部分组成,使用的是MapMap<K,V>接口。
单列集合Collection接口
在单列集合Collection接口下有一些常用的基本方法,首先创建一个集合并导包:
Collection<String> list=new ArrayList<>();
- 新增 :boolean add(E e);
boolean b=list.add("李华");
返回的布尔值表示新增是否成功,在集合里的新增方法都是默认为true,所以一般不接收返回值。
- 删除:boolean remove(Object obj);
b=list.remove("李华");
true表示删除成功,false表示该元素不存在。
- 是否包含: boolean contains(Object obj);
b=list,contains("李华");
true表示集合包含“李华”这个元素,false表示不包含。
- 是否为空:boolean isEmpty();
b=list.isEmpty();
true表示集合为空,false表示集合不为空。
- 集合元素个数:int size();
int n=list.size();
- 将集合转成数组:Object[] toArray();
Object[] object=list.toArray();
- 将集合转成泛型数组: T[ ] toArray(T[ ] arr);
String[] s=new String[list.size()];
list.toArray(s);
System.out.println(Arrays.toString(s));
根据集合泛型创建对应类型数组,利用此方法进行转换并打印。
- 删除集合中的所有元素:void clear();
list.clear();
List接口
List接口下的集合的特点:有索引值、有序、元素可以重复。
List接口下的实现类:
- ArrayList:底层是数组,特点:查询快 增删慢,线程不安全,效率高。
- LinkedList:底层是链表,特点:查询慢 增删快
- Vector(较少使用):和ArrayList类似,特点:线程安全,效率低。
List接口中的方法:
List<Integer> list=new ArrayList<>();
- 在指定位置新增:void add(int index,E e);
list.add(5, 6);
这里的新增方法没有返回值,且有两个参数:索引值和新增元素。上面这行代码表示:在索引值为5处新增元素6.
- 删除指定索引值位置的元素:E remove(int index);
Integer n=list.remove(0);
删除索引值为0处的元素,返回被删除的元素。
- 获取指定索引值位置的元素:E get(int index);
n=list.get(2);
获取索引值为2处的元素。
- 替换:E set(int index,E e);
n=list.set(0, 1);
将索引值为0处的元素替换为1,返回被替换的元素。
- 截取:List subList(int beginIndex,int endIndex);
List<Integer> list1=list.subList(1, 4);
将list集合中,从索引值为1开始,至索引值为3的元素截取到新的集合list1中。
- 获取元素首次出现的索引值:int indexOf(Object o);
int i=list1.indexOf(4);
如果没有该元素,则返回-1;
- 获取元素最后一次出现的索引值:int lastIndexOf(Object o);
i=list1.lastIndexOf(5);
Set接口
Set接口下的集合的特点:没有索引值,元素不可以重复。
Set接口下的实现类:
1.HashSet:无序。底层是哈希表:数组+链表+红黑树。
2.LinkedHashSet:有序。链表+哈希表。
3.TreeSet:可排序。红黑树。
Set集合中不能新增相同的元素。
Set<String> set=new HashSet<>();
set.add("胡歌");
set.add("万茜");
set.add("易烊千玺");
set.add("易烊千玺");//值相同时,不能新增
System.out.println(set);//无序:[易烊千玺, 胡歌, 万茜]
可以看到,set集合新增了4个元素,其中有一个元素是重复的,从输出内容看到:set中只有3个元素,说明重复元素没有新增成功;而且可以看到HashSet的输出顺序和新增顺序是不一样的,说明HashSet是无序的,注意这里的无序指的是输出顺序和新增时不一定相同。
同样的,我们来看一下LinkedHashSet:
Set<String> set1=new LinkedHashSet<>();
set1.add("胡歌");
set1.add("万茜");
set1.add("易烊千玺");
boolean b=set1.add("易烊千玺");//值相同时,不能新增
System.out.println(b);//false
System.out.println(set1);//有序:[胡歌, 万茜, 易烊千玺]
同样的新增内容,LinkedHashSet的输出顺序和新增顺序是一样的,且重复元素也没有新增成功。
如果新增元素是自定义类型的成员变量,需要判断新增元素是否相同:
1.计算新增元素的哈希值(十进制的地址值),调用hashCode();//Object的方法。
2.通过哈希值%数组长度,去确定元素新增的索引值位置
如果该位置没有元素:直接新增
如果该位置有元素:判断这两个元素是否相同
如果不相同:挂到最后一个元素下面
如果相同:不新增
3.判断是否相同的标准:
比较哈希值相同 && (地址值相同 || equals相同)
如果认为成员变量的值相同,就为同一个元素,则需要覆盖重写hashCode方法和equals方法才能实现新增。
TreeSet集合比较特殊,它在进行新增元素的时候,泛型必须是Comparable类型。
- 创建Comparator类型的对象
Comparator<E> c = new Comparator<E>() {
public int compare(E t1, E t2) {
/*
* 升序:
* 参数1-参数2
* 降序:
* 参数2-参数1
*/
int result ;
return result;
}
}
- 实现Comparable接口,重写 compareTo方法
public int compareTo(E o) {
//升序
//int result = this.成员变量-o.成员变量;
//降序
int result = o.成员变量-this.成员变量;
return result;
}
通过这两种方式可以根据需求对元素进行排序。
双列集合
Map<K,V>特点:
- 一个元素是有一个K,一个V两部分组成
- K V可以是任意的引用数据类型
- 一个K对应唯一的一个V、K不能重复
Map<K,V>常用实现类:
- HashMap:底层是哈希表,无序,线程不安全,效率高。
- LinkedHashMap:底层是链表+哈希表,有序。
- TreeMap:底层是红黑树,可排序。
- Hashtable:线程安全,效率低,K和V不可以为null。
Map<K,V>常用方法:
- 新增:V put(K k,V v);
Map<String,Integer> map=new HashMap<>();
Integer v=map.put("胡歌", 39);
System.out.println(v);//null
v=map.put("胡歌", 20);
System.out.println(v);//39
如果K不存在,则返回null;如果K存在,则新的V替换旧的V,返回被替换的V。
-删除: V remove(Object key);
v=map.remove("李四");
System.out.println(v);//38
v=map.remove("张三");
System.out.println(v);//null
根据key删除整个元素,返回被删除元素的V;如果Key不存在,则返回null。
- 获取:V get(Object key);
v=map.get("胡歌");
System.out.println(v);//20
根据key获取V,如果key不存在则返回null。
- 包含key:boolean containsKey(Object key);
- 包含value: boolean containsValue(Object value);
boolean b=map.containsKey("胡歌");
b=map.containsValue(36);
- 获取所有的K:Set keySet();
- 获取所有的V:Collection values();
Set<String> key=map.keySet();
Collection<Integer> values=map.values();
集合的遍历
集合的遍历可以通过迭代器Iterator实现:
Collection<String> c=new ArrayList<>();
c.add("胡歌");
c.add("易烊千玺");
c.add("朱一龙");
System.out.println(c);
//获取迭代器对象
Iterator<String> ite=c.iterator();
while(ite.hasNext()) {
String s=ite.next();
System.out.println(s);
//通过迭代器进行新增
if(s.equals("易烊千玺")) {
ite.remove();
}
}
需要注意的是:在利用迭代器进行遍历的时候,要先利用hasNext()方法判断下一个是否有元素,如果为true则继续进行,利用next()获取下一个元素,进行遍历;通过迭代器遍历集合的时候,不能通过集合对象增、删元素,如果要删除可以通过迭代器对象的删除方法删。
还有一种方法:增强for循环。增强for循环的底层是迭代器,但是其形式较为简单:
//增强for循环
for(String name:c) {
System.out.println(name);
}
那么对于双列集合如何实现遍历呢?需要将双列集合转成单列集合,具体有两种方法:
第一种:获取所有的K,通过K再获取V。
Map<String,Double> map = new HashMap<>();
map.put("张三", 90.0);
map.put("张三丰", 99.0);
map.put("李四", 90.0);
//获取所有的K
Set<String> key=map.keySet();
System.out.println(key);
//遍历
for(String k:key) {
//根据key获取V
Double v=map.get(k);
System.out.println(k+"--"+v);
}
第二种:通过Entry<K,V>接口进行实现:
Set<Entry<String,Double>> entry=map.entrySet();
Iterator<Entry<String, Double>> iterator = entry.iterator();
while(iterator.hasNext()) {
Entry<String, Double> e=iterator.next();
String k=e.getKey();
Double value=e.getValue();
System.out.println(k+"--"+value);
}
转成单列集合后就可以使用迭代器和增强for循环进行遍利了。
以上就是我对集合的整理。