学习的目标:
- 会使用集合存储数据
- 会遍历集合取出数据
- 掌握各个集合的特性,不同的业务场景使用响应的集合
一,集合概述
- 集合:用来存储数据的容器,与数组不同,一个集合可以存储多种类型的引用对象,并且长度可以变
- 框架
- List接口的元素是有序,不重复,有索引的
- Set接口的远是无索引,可以重复的
- TreeSet,HashSet的数据是无序的,LinkedHashSet的元素是有序的
二,具体接口方法的学习
目录:
- collection接口的方法
- Iterator迭代器
- 增强for循环
- List接口
- ArrayList集合
- LinkList集合
- Vector
- Set接口
- TreeSet集合
- HashSet集合
- LinkedHashSet集合
- Map接口
- HashTable集合
- HashMap集合
- LinkedHashMap集合
1,collection接口的方法:
- public boolean add(E e):把给定 的对象添加到当前集合中。
- public void clear() :清空集合中所有的元素。
- public boolean remove(E e):把给定的对象在当前集合中删除。
- public boolean contains(E e):判断当前集合中是否包含给定的对象。
- public boolean isEmpty()::判断当前集合是否为空。
- public int size(): 返回集合中元素的个数。
- public object[] toArray()::把集合中的元素,存储到数组中。
- 练习:
class test{
public static void main(String[] args) {
//创建集合对象(接口指向实现类的引用——》设计多态)
Collection collection=new ArrayList<>();
collection.add("A");
collection.add("B");//返回值为true,说明添加成功
collection.add("C");
System.out.println(collection);
collection.remove("B");//返回值为true删除成功
collection.remove("D");//返回值为false,删除失败
System.out.println(collection);
System.out.println(collection.contains("A"));//判断集合是否包含元素
System.out.println(collection.contains("B"));
System.out.println(collection.isEmpty());//判断集合是否为空
System.out.println(collection.size());//打印集合的长度
Object [] ary=collection.toArray();//把集合变数组
for (int i=0;i<ary.length;i++){
System.out.println(ary[i]);
}
collection.clear();//清空集合中的数据
System.out.println(collection);
}
}
2,Iterator迭代器:
- 迭代器的产生:因为有很多集合,每个集合的遍历方式多多多少少有点不同,如果每个集合都去实现一个变量的方法就太过于繁杂于是出现了Iterator迭代器,专门遍历集合元素
- 迭代过程:先判断集合中有没有元素,如果有就取出第一个元素,再次判断集合有没有元素,再取出。直到集合中没有元素,就停止迭代。
- 迭代器对象的获取:Iterator iterator = collection.iterator();
- 练习:
class test{
public static void main(String[] args) {
//创建集合对象(接口指向实现类的引用——》设计多态)
Collection collection=new ArrayList<>();
collection.add("A");
collection.add("B");//返回值为true,说明添加成功
collection.add("C");
Iterator iterator = collection.iterator();//获取迭代器对象
while (iterator.hasNext()){
System.out.println(iterator.next());//取出下一个元素,指向集合元素的指针向后移动
}
}
}
3,增强for循环:遍历的目标只能是集合或数组
class test{
public static void main(String[] args) {
//创建集合对象(接口指向实现类的引用——》设计多态)
Collection collection=new ArrayList<>();
collection.add("A");
collection.add("B");//返回值为true,说明添加成功
collection.add("C");
for (Object info:collection){//遍历的目标只能是集合或数组
info=(String)info;
System.out.println(info);
}
}
}
4,List接口
特点:
- 是有序集合,存储的元素和取出的元素顺序是一致的
- 因为List是基于数组的,所以每个元素有索引、
- 允许存储值相同的元素
带索引的方法有:
- public void add(int index, E element): 将指定的元素,添加到该集合中的指定位置上。
- public E get(int index) :返回集合中指定位置的元素。
- public E remove(int index): 移除列表中指定位置的元素,返回的是被移除的元素。
- public E set(int index, E element) :用指定元素替换集合中指定位置的元素,返回值的更新前的元素。
- 练习:以实现类ArrayList为例
class test{
public static void main(String[] args) {
List list=new ArrayList();
list.add("a");
list.add("b");
list.add("c");
System.out.println(list);//打印有序
list.add(2,"i love you");//指定位置添加元素
System.out.println(list);
Object remove = list.remove(3);//移除元素
System.out.println("移除的元素是:"+remove);
list.set(0,"A");//替换元素
System.out.println(list);
System.out.println("第一元素是:"+list.get(0));//用get方法获取元素
}
static void print(){
}
}
5,ArrayList集合
- 查询快,增加删除慢
- 底层会调用一个数组复制的方法来进行数组长度加一,添加新的元素
6,LinkList集合
TinkedList集合的特点:
- 底层是一个链表结构:查询慢,增删快
- 里边包含了大量操作首尾元素的方法
- 注意:使用L inkedList集合特有的方法,不能使用多态
方法:
- public void addFirst(E e):将指定元素插入此列表的开头。
- public void addLast(E e):将指定元素添加到此列表的结尾。
- public void push(E e):将元素推入此列表所表示的堆栈。
- public E getFirst():返回此列表的第一 个元素。
- public E getLast():返回此列表的最后一 个元素。
- public E removeFirst():移除并返回此列表的第- 个元素。
- public E removeLast():移除并返回此列表的最后- -个元素。
- public E pop():从此列表所表示的堆栈处弹出- -个元素。
- public boolean isEmpty(): 如果列表不包含元素,则返回true。
- 练习:
class test{
public static void main(String[] args) {
LinkedList<String> list=new LinkedList<>();
list.add("a");
list.add("b");
list.add("c");
System.out.println(list);//打印有序
list.addFirst("i love you");//链头添加元素
list.addLast("www");//链尾添加元素
System.out.println(list);
if(!list.isEmpty()){
String first = list.getFirst();//获取链头,如果集合中没有元素会报错,所以添加一个判断
String last = list.getLast();//获取链尾
System.out.println("首元素"+first+" 尾元素 "+last);
}
String removeFirst = list.removeFirst();//和pop功能一样
String pop = list.pop();
String removeLast = list.removeLast();
System.out.println("pop出的元素是"+pop);
System.out.println("首元素"+removeFirst+" 尾元素 "+removeLast);
System.out.println(list);
}
}
7,Vector
- 底层是数组,是单线程的,所以线程安全
- addElement方法来添加元素
- elements方法来返回所有元素的枚举,使用枚举接口中的hasMoreElement方法来判断是否集合中有元素,如果有元素就用nextElement方法来遍历元素
8,Set接口
- 不允许存储重复元素
- 没有索引,所以不能使用带索引的方法,也就不能用for循环遍历
9,HashSet集合
- 特点:不允许存储重复元素,没有索引,是一个无序集合,底层是一个哈希表结构查询快
- 哈希值:是一个十进制的整数,是对象的逻辑地址值,Object类中有hashCode方法可以获取对象的哈希值,该方法是native方法
- 哈希表:数组+链表+红黑树,数组中存哈希值,链表中存对应哈希值的元素,红黑树是jdk1.8添加的,用来提高查找效率
- 为什么set集合中不能存储重复的元素?
使用add方法来添加元素,add方法会调用equal方法和hashCode方法来判断元素重复。
如:set.add("new String("abc")); add方法会调用hashCode方法计算abc字符串的哈希值为98876,遍历哈希表的数组,看看是否有98876的哈希值存入,
如果没有就存入哈希值,就把abc字符串元素插入链表中,判断链表长度是否大于8,如果大于8就链表结构转成红黑树结构。
如果该哈希值已经在哈希表的数组中存在了,就遍历该哈希值对应的链表中的元素,看看是否有元素值为abc,如果有就不存如,如果没有就存入元素。
- 使用HashSet存储自定义元素练习
- Student类要重写它的equals方法和hashCode方法
public class Student {
private int age;
private String name;
public Student(){
}
public Student(int age,String name){
this.age=age;
this.name=name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(age, name);
}
}
测试类:
import java.util.HashSet;
import java.util.LinkedHashSet;
public class HashSetTest {
public static void main(String[] args) {
Student s1=new Student(20,"建江");
Student s2=new Student(20,"建江1");
Student s3=new Student(20,"建江2");
Student s4=new Student(20,"建江");
HashSet<Student> set=new HashSet<>();//无序
set.add(s1);
set.add(s2);
set.add(s3);
set.add(s4);
System.out.println(set);
LinkedHashSet<Student> set1=new LinkedHashSet<>();//有序
set1.add(s1);
set1.add(s2);
set1.add(s3);
set1.add(s4);
System.out.println(set1);
}
}
11,LinkedHashSet集合:是一个有序不可以重复的集合,有一个链表用来记录集合元素的下标
12,Map<k,v>接口:在java.util包下
- 该接口的泛型有两个值:key和value,key是唯一的,并且一个key对应一个value
- put(key,value)方法,向集合中添加元素,如果元素存在就覆盖元素
- remove(key)方法,移除集合中的元素,返回对应元素的值,如果元素不存在就返回null
- get(key)方法:用来获取对应的值
- containsKey()方法用来判断集合中是否有对应的值
- keySet()方法以set集合的形式返回该集合的所有key值,用于遍历Map集合
- 各个函数的练习,集合的遍历
public class HashMapTest {
public static void main(String[] args) {
HashMap<String,String> map=new HashMap<String, String>();
map.put("建江","小妹");//put()方法
map.put("小米","小王");
map.put("小丽","小俊");
map.put("小鬼","大叔");
System.out.println(map.get("建江"));//get("建江")
System.out.println(map);
String element = map.remove("建江");//remove("建江");
System.out.println(element);
System.out.println(map);
System.out.println("集合中还有建江吗:"+map.containsKey("建江"));//containsKey("建江")
//遍历Map集合的第一种方式
Set<String> set = map.keySet();//获取所以的key值存入set集合中
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()){
String key = iterator.next();
System.out.println(key+":"+map.get(key));
}
System.out.println("==========================");
for (String key:set){
System.out.println(key+":"+map.get(key));
}
System.out.println("==========================");
//遍历Map集合的第二种方式
Set<Map.Entry<String, String>> entries = map.entrySet();//将entry对象存到set集合中
Iterator<Map.Entry<String, String>> iterator1 = entries.iterator();//获取对应的迭代器
while (iterator1.hasNext()){
Map.Entry<String, String> entry = iterator1.next();//获取到每个entry对象
String key=entry.getKey();
String value=entry.getValue();
System.out.println(key+":"+value);
}
}
}
13,HashTable集合:不能存null值和null键(已经被取代)
14,HashMap集合
15,LinkedHashMap集合:继承HashTable集合,是一个有序集合
public class HashMapTest {
public static void main(String[] args) {
HashMap<String,Student> map=new HashMap<String, Student>();
map.put("计算机1班",new Student(19,"陈建江"));
map.put("计算机2班",new Student(20,"丽丽"));
map.put("计算机3班",new Student(21,"美美"));
map.put("计算机4班",new Student(22,"小明"));
System.out.println(map);
LinkedHashMap<String,Student> map1=new LinkedHashMap<String, Student>();//有序集合
map1.put("计算机1班",new Student(19,"陈建江"));
map1.put("计算机2班",new Student(20,"丽丽"));
map1.put("计算机3班",new Student(21,"美美"));
map1.put("计算机4班",new Student(22,"小明"));
System.out.println(map1);
}
}
16,练习:统计一个字符串中每个字符的个数
public class Test {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
while (true){
System.out.print("请输入一个字符串:");
String info = scanner.next();
Map<Character,Integer> map=new HashMap<>();
for (char c:info.toCharArray()){
if (map.containsKey(c)){
Integer value = map.get(c);
value++;
map.put(c,value);
}else {
map.put(c,1);
}
}
System.out.println(map);
}
}
}