● 集合概念
集合-->容器
数组:同一种类型,长度固定不可变,每一个元素都有索引,索引从0开始
数组在实际中的不便:
数组长度不可变
现实中程序运行时数据量是可以改变的,需要能够满足可变的需求
有的时候想存储不可重复的数据,有的时候想对元素进行排序
所以java提供了许多不同特征的容器类
集合
单列集合:
Collection里面定义了单列集合共有的方法
List 可存储重复元素
实现类:
ArrayList数组实现
LinkedList链表实现
Vector 数组实现线程安全的
Set 不可存储重复元素
实现类:
HashSet
TreeSet
双列集合:
Map mapping映射 键 值
实现类
HashMap
TreeMap
HashTable
●Collection 接口
● Collection 接口-定义了存取一组对象的方法,其子接口Set和List分别定义 了存储方式。
● Set 中的数据对象不可以重复。
● List 中的数据对象有顺序(添加顺序)且可以重复。
● List 接口及实现类
ArrayList
可以保存重复元素,底层是数组实例,添加元素的类型可以是任意类型
虽然集合默认可以添加任意数据类型,但是后续处理时会产生类型转换类型
所以java中的集合类都支持自定义类型(泛型 把类型当做参数传递)
底层是一个数组,默认长度是10,当数组装满时,会自动扩容
数组利用率可能会浪费
ArrayList<String> 定义时,为集合中可以存储的数据设计一个类型,必须是类 类型
好处:一个集合只能存储一种类型
ArrayList的常用方法
add(E element)
向末尾添加元素,会自动扩容
add(int index, E element)
向指定位置添加元素,位置从0开始到size(实际装入元素个数)
get(int index)
获取指定位置的元素
indexOf(Object o)
获取指定元素第一次出现的索引
lastIndexOf(Object o)
获取指定元素最后一次出现的索引
remove(int index)
删除并返回指定位置上的元素
set(int index, E element)
替换集合中指定位置的元素
isEmpty(E element)
判断集合是否为空,是为true,否则为false
contains()
判断是否包含指定的元素
clear()
清空集合中的元素
size()
获得集合中实际元素的个数,也可以是集合的长度
package day12集合.list;
import java.util.ArrayList;
public class ArrayListDemo2 {
/*
List接口实现类
add
ArrayList 可以保存重复元素,底层是数组实例,添加元素的类型可以是任意类型
虽然集合默认可以添加任意数据类型,但是后续处理时会产生类型转换类型
所以java中的集合类都支持自定义类型(泛型 把类型当做参数传递)
底层是一个数组,默认长度是10,当数组装满时,会自动扩容
数组利用率可能会浪费
*/
public static void main(String[] args) {
ArrayList<String> arrayList1=new ArrayList<>();
arrayList1.add("a");//向末尾添加元素,会自动扩容
arrayList1.add("b");
arrayList1.add("c");
arrayList1.add("d");
arrayList1.add("e");
arrayList1.add("f");
arrayList1.add("g");
arrayList1.add("b");
arrayList1.add("b");
arrayList1.add("b");
arrayList1.add(10, "X");//向指定位置添加元素,位置从0开始到size(实际装入元素个数)
arrayList1.remove("b");//根据元素的内容删除数据,只删除匹配的第一个元素
String s=arrayList1.remove(2);//删除并返回指定位置上的元素8
System.out.println(s);
//arrayList1.clear(); 清空集合中的元素
System.out.println(arrayList1);
System.out.println(arrayList1.contains("t"));//判断是否包含指定的元素
System.out.println(arrayList1.get(2));//获取指定位置的元素
System.out.println(arrayList1.indexOf("a")); //获取指定元素第一次出现的索引
System.out.println(arrayList1.lastIndexOf("a"));//获取指定元素最后一次出现的索引
System.out.println(arrayList1.isEmpty());//判断集合是否为空,是为true,否则为false
arrayList1.set(1, "A");//替换集合中指定位置的元素
System.out.println(arrayList1);
System.out.println(arrayList1.size());//获得集合中实际元素的个数,也可以是集合的长度
}
}
LinkedList
底层是链表实现,每一个数据封装在一个Node对象中
查询慢,中间增加,删除速度快,元素不需要移动,只需要改变地址值
package day12集合.list;
import java.util.LinkedList;
public class LinkedListDemo {
public static void main(String[] args) {
LinkedList<String> linkedList=new LinkedList<>();
linkedList.add("a");
linkedList.add("b");
linkedList.add("c");
linkedList.add("d");
linkedList.add("e");//向链末尾添加元素
System.out.println(linkedList);
System.out.println(linkedList.get(3));//链表获取指定位置的元素(从头或从尾开始查找)
//linkedList.clear();
System.out.println(linkedList);
}
}
Vector
数组实现多线程安全的
package day12集合.list;
import java.util.Vector;
public class VectorDemo {
public static void main(String[] args) {
Vector<Integer> vector=new Vector<>();
vector.add(1);
vector.add(2);
vector.add(3);
vector.add(4);
vector.add(5);
vector.add(6);
vector.add(7);
vector.add(8);
vector.add(9);
vector.add(10);
vector.add(11);
}
}
● List接口集合迭代
● for循环遍历
● 增强for循环的遍历
● 迭代器遍历(Iterator)
package day12集合.list;
import java.util.ArrayList;
import java.util.Iterator;
public class ArrayListDemo3 {
public static void main(String[] args) {
ArrayList<String> arrayList=new ArrayList<>();
arrayList.add("a");
arrayList.add("b");
arrayList.add("c");
//1.for循环
for(int i=0;i<arrayList.size();i++){
System.out.println(arrayList.get(i));
}
//2.增强for循环
for(String s:arrayList){
System.out.println(s);
}
//3.使用迭代器
Iterator<String> iterator=arrayList.iterator();
while(iterator.hasNext()){
String s=iterator.next();
System.out.println(s);
}
}
}
● Set 接口(Set 接口类不能存储重复元素,与List方法类似)
HashSet
元素是无序的(既不是添加的顺序,也不是自然顺序)
向HashSet中添加元素时,是如何判断元素是否重复
添加元素时,调用equals()判断,效率低(一个一个字符判断)
底层用到hashCode() 和equals() 方法
用内容计算hash值(整数),用hash比较速度快
但是hash值是不安全的,有可能hash内容不同,计算的hash值相同
当hash值相同时调用equals()判断内容是否相等
这样效率提高,也保证安全
package day12集合.set;
import java.util.HashSet;
public class HashSetDemo2 {
public static void main(String[] args) {
HashSet<String> hashSet=new HashSet<>();
hashSet.add("xdas");
hashSet.add("a");
hashSet.add("s");
hashSet.add("h");
hashSet.add("b");
hashSet.add("xdas");
hashSet.add("通话");
hashSet.add("重地");
System.out.println(hashSet);
}
}
package day12集合.set;
public class Student implements Comparable<Student>{
private int num;
private String name;
public Student(int num, String name) {
this.num = num;
this.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;
if (num != student.num) return false;
return name != null ? name.equals(student.name) : student.name == null;
}
@Override
public int hashCode() {
int result = num;
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "Student{" +
"num=" + num +
", name='" + name + '\'' +
'}';
}
@Override
public int compareTo(Student o) {
return o.num-this.num;
}
}
package day12集合.set;
import java.util.HashSet;
import java.util.Iterator;
public class HashSetDemo3 {
public static void main(String[] args) {
HashSet<Student> set=new HashSet<>();
Student student1=new Student(101,"张三");
Student student2=new Student(102,"李四");
Student student3=new Student(103,"王五");
Student student4=new Student(101,"张三");
/*
添加时,判断时调用类中hashCode(),计算hash值,类中,没有hashCode(),会调用父类的hashCode()
Object类中的public native int hashCode(); native本地方法
所以只要是new出来的,调用Object类中的hash值,是内存地址,肯定不相同
如果我们想要对象中的内容相等就判断为重复元素,就必须在类中重写 hashCode() equals() ,用对象中的内容计算hash值
*/
set.add(student1);
set.add(student2);
set.add(student3);
set.add(student4);
System.out.println(set);
for(Student student:set){
System.out.println(student);
}
System.out.println("========================");
Iterator<Student> iterator= set.iterator();
while(iterator.hasNext()){
Student s= iterator.next();
System.out.println(s);
}
}
}
● Map 接口
Map接口常用方法
get(K key)
通过key获取到key所对应的value
clear()
清空所有键值映射
put(K key,V value)
添加键值对
remove(K key)
删除键值映射,并返回该键对应的值
containsKey(K key)
判断键是否存在
containsValue(V value)
判断值是否存在
size()
返回键值映射关系的个数
isEmpty()
判断是否为空
键 值对
键不能重复,值可以重复
一个键映射到一个值
HashMap
键是无序的
package day12集合.map;
import java.util.Collection;
import java.util.HashMap;
import java.util.Set;
public class HashMapDemo1 {
public static void main(String[] args) {
HashMap<String,String> map=new HashMap<>();
map.put("c", "cc");
map.put("x", "xx");
map.put("a", "aa");
map.put("h", "hh");
map.put("c", "CC");
System.out.println(map.get("x"));//通过key获取到key所对应的value
//map.clear();//清空所有键值映射
System.out.println(map.remove("x"));//删除键值映射,并返回该键对应的值
System.out.println(map.containsKey("x"));//判断键是否存在
System.out.println(map.containsValue("hh"));//判断值是否存在
System.out.println(map.size());//返回键值映射关系的个数
System.out.println(map.isEmpty());//判断是否为空
Collection<String> values=map.values();
System.out.println(values);
Set<String> keys=map.keySet();
System.out.println(keys);
System.out.println(map);
}
}
TreeMap
键可以排序,键的类型必须实现Comparable()接口
package day12集合.map;
import java.util.TreeMap;
public class TreeMapDemo {
public static void main(String[] args) {
TreeMap<String,String> tmap=new TreeMap<>();
tmap.put("c","c");
tmap.put("a","a");
tmap.put("b","b");
tmap.put("d","d");
System.out.println(tmap);
}
}
Hashtable
键值不能为空
Hashtable不允许存储为null的键和值
Hashmap可以存储为null的键,值也可以为null
底层结构与HashMap相同,但是线程是安全的 方法添加了synchronized
package day12集合.map;
import java.util.Hashtable;
public class HashTableDemo {
public static void main(String[] args) {
Hashtable<String,String> hmap=new Hashtable<>();
hmap.put("x", "x");
hmap.put("a", "a");
hmap.put("g", "g");
hmap.put("r", "r");
hmap.put("x", "x");
hmap.put(null, null);//NullPointerException
System.out.println(hmap);
}
}
Map集合遍历
方式1:根据键找值
• 获取所有键的集合
• 遍历键的集合,获取到每一个键
• 根据键找值
方式2:根据键值对对象找键和值
• 获取所有键值对对象的集合
• 遍历键值对对象的集合,获取到每一个键值对对象
• 根据键值对对象找键和值
package day12集合.map;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class HashMapDemo3 {
public static void main(String[] args) {
HashMap<String,String> map=new HashMap<>();
map.put("c", "cc");
map.put("x", "xx");
map.put("a", "aa");
map.put("h", "hh");
map.put("c", "CC");
//方法1: keySet() 获取所有的键 遍历键的集合
Set<String> keyset= map.keySet();
for(String key:keyset){
System.out.println(key+":"+map.get(key));
}
//方法2:通过entrySet() 获得一个Entry类型的集合,Entry中放有键值
Set<Map.Entry<String,String>> entries=map.entrySet();
for(Map.Entry entry:entries){
System.out.println(entry.getKey()+":"+entry.getValue());
}
}
}