javaSE_day10_集合_迭代器_增强for_泛型_List接口_ArrayList_LinkedList_Vector_Set_HashSet_Map__可变参数
1.介绍
集合是一种容器,可以用来存储多个数据
2.集合和数组的区别
数组的长度是固定的,集合的长度是可变的
集合中存储的元素必须是引用数据类型
3.集合继承关系
Collection接口为最顶层集合接口了
Collecton接口常用的子接口有:List接口、Set接口
List接口常用的子类有:ArrayList类、LinkedList类
Set接口常用的子类有:HashSet类、LinkedHashSet类
4.迭代器
java中提供了很多个集合,它们在存储元素时,采用的存储方式不同。 我们要取出这些集合中的元素,可通过一种通用的获取方式来完成
Collection集合元素的通用获取方式:在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。
接口 Iterator : 两个抽象方法:
boolean hasNext() 判断集合中还有没有可以被取出的元素,如果有返回true
next() 取出集合中的下一个元素
package com.day10;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Test01 {
public static void main(String[] args) {
Collection<String> coll=new ArrayList<String>();
coll.add("www.");
coll.add("baidu");
coll.add(".com");
Iterator<String> it = coll.iterator();
while (it.hasNext()) {
String str=it.next();
System.out.println(str);
}
}
}
5.增强for
格式:
for( 数据类型 变量名 : 数组或者集合 ){
输出(变量);
}
例:for (String string : coll) {
System.out.println(string);
}
好处: 代码少了,方便对容器遍历
弊端: 没有索引,不能操作容器里面的元素
6.泛型(新的安全机制,保证程序的安全性)
泛型: 指明了集合中存储数据的类型 <数据类型>
泛型的通配,匹配所有的数据类型 ?
7.List接口
特点:有序,可重复元素,索引
实现子类:ArrayList LinkedList
常用的方法:
增加元素方法:
add(Object e):向集合末尾处,添加指定的元素
add(int index, Object e):向集合指定索引处,添加指定的元素,原有元素依次后移
删除元素删除:
remove(Object e):将指定元素对象,从集合中删除,返回值为被删除的元素
remove(int index):将指定索引处的元素,从集合中删除,返回值为被删除的元素
替换元素方法:
set(int index, Object e):将指定索引处的元素,替换成指定的元素,返回值为替换前的元素
查询元素方法:
get(int index):获取指定索引处的元素,并返回该元素
8.Iterator的并发修改异常
在迭代过程中,使用了集合的方法对元素进行操作。导致迭代器并不知道集合中的变化,容易引发数据的不确定性。
出现的异常:java.util.ConcurrentModificationException
并发修改异常解决办法:在迭代时,不要修改集合的长度,也就是不要使用add方法。
9.List集合存储数据的结构:堆栈,队列,数组,链表
堆栈:特点是先进后出,压栈就是存元素,弹栈就是取元素
队列:特点是先进先出
数组:查找元素快,增删元素慢
链表:多个节点之间,通过地址进行连接,查找元素慢,增删元素快
10.ArrayList集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList是最常用的集合
11.LinkedList集合
数据存储的结构是链表结构。方便元素添加、删除的集合。实际开发中对一个集合元素的添加与删除经常涉及到首尾操作
LinkedList主要方法
例:
LinkedList<String> link = new LinkedList<String>();
//添加元素
link.addFirst("abc1");
link.addFirst("abc2");
link.addFirst("abc3");
//获取元素
System.out.println(link.getFirst());
System.out.println(link.getLast());
//删除元素
System.out.println(link.removeFirst());
System.out.println(link.removeLast());
while(!link.isEmpty()){ //判断集合是否为空
System.out.println(link.pop()); //弹出集合中的栈顶元素
12.Vector集合
Vector集合数据存储的结构是数组结构,Vector中提供了一个独特的取出方式,就是枚举Enumeration
Vector常见的方法:
Enumeration枚举常见的方法:
Vector集合对ArrayList集合使用的对比
13.Set接口
List中是可以存放重复元素的,Set所存储的元素就是不重复的
素的equals方法,来判断是否为重复元素
集合取出的元素的方式采用:迭代器和增强for
set的实现类:HashSet和LikedHashSet
14.HashSet
底层数据结构是哈希表
15.List与Set知识点总结
List与Set集合的区别?
List:
它是一个有序的集合(元素存与取的顺序相同)
它可以存储重复的元素
Set:
它是一个无序的集合(元素存与取的顺序可能不同)
它不能存储重复的元素
List集合中的特有方法:
void add(int index, Object element) 将指定的元素,添加到该集合中的指定位置上
Object get(int index)返回集合中指定位置的元素。
Object remove(int index) 移除列表中指定位置的元素, 返回的是被移除的元素
Object set(int index, Object element)用指定元素替换集合中指定位置的元素,返回值的更新前的元素
ArrayList:
底层数据结构是数组,查询快,增删慢
LinkedList:
底层数据结构是链表,查询慢,增删快
HashSet:
元素唯一,不能重复
底层结构是 哈希表结构
元素的存与取的顺序不能保证一致
如何保证元素的唯一的?
重写hashCode() 与 equals()方法
LinkedHashSet:
元素唯一不能重复
底层结构是 哈希表结构 + 链表结构
元素的存与取的顺序一致
16.Map接口
Map接口和Collection接口的不同:
Map接口下的集合与Collection接口下的集合,它们存储数据的形式不同
Collection中的集合,元素是孤立存在的,向集合中存储元素采用一个个元素的方式存储。
Map中的集合,元素是成对存在的。每个元素由键与值两部分组成,通过键可以找对所对应的值。
Collection中的集合称为单列集合,Map中的集合称为双列集合。
需要注意的是,Map中的集合不能包含重复的键,值可以重复;每个键只能对应一个值。
Map接口中常用子类的集合为HashMap集合、LinkedHashMap集合
HashMap<K,V>:存储数据采用的哈希表结构,元素的存取顺序不能保证一致
LinkedHashMap<K,V>:HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构
注意:Map接口中的集合都有两个泛型变量<K,V>,在使用时,要为两个泛型变量赋予数据类型。两个泛型变量<K,V>的数据类型可以相同,也可以不同
Map的常用方法:
例
public class MapDemo {
public static void main(String[] args) {
//创建Map对象
Map<String, String> map = new HashMap<String,String>();
//给map中添加元素
map.put("星期一", "Monday");
map.put("星期日", "Sunday");
System.out.println(map); // {星期日=Sunday, 星期一=Monday}
//当给Map中添加元素,会返回key对应的原来的value值,若key没有对应的值,返回null
System.out.println(map.put("星期一", "Mon")); // Monday
System.out.println(map); // {星期日=Sunday, 星期一=Mon}
//根据指定的key获取对应的value
String en = map.get("星期日");
System.out.println(en); // Sunday
//根据key删除元素,会返回key对应的value值
String value = map.remove("星期日");
System.out.println(value); // Sunday
System.out.println(map); // {星期一=Mon}
Map集合遍历:通过键找值;遍历键值对方式
Map集合遍历键找值:
keySet()方法
例:
public class MapDemo {
public static void main(String[] args) {
//创建Map对象
Map<String, String> map = new HashMap<String,String>();
//给map中添加元素
map.put("邓超", "孙俪");
map.put("李晨", "范冰冰");
map.put("刘德华", "柳岩");
//获取Map中的所有key
Set<String> keySet = map.keySet();
//遍历存放所有key的Set集合
Iterator<String> it =keySet.iterator();
while(it.hasNext()){
//得到每一个key
String key = it.next();
//通过key获取对应的value
String value = map.get(key);
System.out.println(key+"="+value);
}
}
}
Map集合遍历键值对方式
即通过集合中每个键值对(Entry)对象,获取键值对(Entry)对象中的键与值
public class MapDemo {
public static void main(String[] args) {
//创建Map对象
Map<String, String> map = new HashMap<String,String>();
//给map中添加元素
map.put("邓超", "孙俪");
map.put("李晨", "范冰冰");
map.put("刘德华", "柳岩");
//获取Map中的所有key与value的对应关系
Set<Map.Entry<String,String>> entrySet = map.entrySet();
//遍历Set集合
Iterator<Map.Entry<String,String>> it =entrySet.iterator();
while(it.hasNext()){
//得到每一对对应关系
Map.Entry<String,String> entry = it.next();
//通过每一对对应关系获取对应的key
String key = entry.getKey();
//通过每一对对应关系获取对应的value
String value = entry.getValue();
System.out.println(key+"="+value);
}
}
}
注意:Map集合不能直接使用迭代器或者foreach进行遍历。但是转成Set之后就可以使用了。
HashMap存储自定义类型键值
例:Person类
package com.day10;
public class Person {
private String name;
private int age;
public Person() {}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
//重写对象的hashCode和equals方法,保证对象传入的值的唯一性
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
Test类:
public class HashMapTest {
public static void main(String[] args) {
//1,创建hashmap集合对象。
Map<Person,String> map = new HashMap<Person,String>();
//2,添加元素。
map.put(new Person("lisi",28), "上海");
map.put(new Person("wangwu",22), "北京");
map.put(new Person("zhaoliu",24), "成都");
map.put(new Person("zhouqi",25), "广州");
map.put(new Person("wangwu",22), "南京");
//3,取出元素。键找值方式
Set<Person> keySet = map.keySet();
for(Person key : keySet){
String value = map.get(key);
System.out.println(key.toString()+"....."+value);
}
//取出元素。键值对方式
Set<Map.Entry<Person, String>> entrySet = map.entrySet();
for (Map.Entry<Person, String> entry : entrySet) {
Person key = entry.getKey();
Person value = entry.getValue();
System.out.println(key.toString()+"....."+value);
}
}
}
注意:
当给HashMap中存放自定义对象时,如果自定义对象作为key存在,这时要保证对象唯一,必须复写对象的hashCode和equals方法(如果忘记,请回顾HashSet存放自定义对象)。
如果要保证map中存放的key和取出的顺序一致,可以使用LinkedHashMap集合来存放。
可变参数:
前提:参数的数据类型确定,但参数个数不确定
语法格式:数据类型...变量名
demo:
public class Test03 {
public static void main(String[] args) {
System.out.println(getSum(11,12,13,18));
}
private static int getSum(int...a) {
int sum=0;
for (int i : a) {
sum+=i;
}
return sum;
}
}
注意:一个方法中,只能有一个可变参数
可变参数必须写在参数列表的最后一位
Map知识点总结
Map集合:
map集合中的元素都是成对出现,成对存储的
map集合中的元素都是以一对键和值的形式组成存在的,称为键值对,理解为夫妻对
map集合中的键不能重复存储,值可以重复
map集合中的每一个键 对应着一个值
方法:
V put(K key, V value) 把指定的键与指定的值添加到Map集合中
V remove(Object key) 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值
Set<Map.Entry<K,V>> entrySet() 获取到Map集合中所有的键值对对象的集合(Set集合)
V get(Object key) 根据指定的键,在Map集合中获取对应的值
Set<K> keySet() 获取Map集合中所有的键,存储到Set集合中
Map集合遍历的两种方式
方式1:根据键找值的方式
//a, 获取到Map集合中所有的键,返回对应的Set集合
//b, 遍历键的集合,获取到每一个键
//c, 通过键,找到对应的值
//获取到Map集合中所有的键,返回对应的Set集合
Set<String> keys = map.keySet();
//遍历键的集合,获取到每一个键
for (String key : keys) {
//通过键,找到对应的值
Student s = map.get(key);
System.out.println( key + "..." + s.getName() + "..." + s.getAge() );
}
方式2:根据键值对对象找键和值的方式
//a, 获取Map集合中所有的键值对元素,返回对应的Set集合
//b, 遍历键值对元素集合,获取到每一个键值对元素对象
//c, 通过键值对元素对象,获取对应的键,和对应的值
//获取Map集合中所有的键值对元素,返回对应的Set集合
Set< Map.Entry<String, Student>> entrySet = map.entrySet();
//遍历键值对元素集合,获取到每一个键值对元素对象
for (Map.Entry<String, Student> entry : entrySet) {
//通过键值对元素对象,获取对应的键,和对应的值
//找键
String key = entry.getKey();
//找值
Student s = entry.getValue();
//打印
System.out.println( key+"..."+s.getName()+"..."+s.getAge() );
}
HashMap:
特点:
是Map集合的子集合
底层采用哈希表结构
HashMap集合中的key不能重复,通过重写hashCode() 与 equals()方法来保证键的唯一。
不能保证元素存与取的顺序完全一致
LinkedHashMap:
特点:
是HashMap集合的子集合
底层采用哈希表+链表结构
LinkedHashMap集合中的key不能重复,通过重写hashCode() 与 equals()方法来保证键的唯一。
Collections中的方法:
public static <T> void sort(List<T> list) 排序
public static void shuffle(List<?> list) 集合中的元素存储位置随机打乱