概述
Java集合类存放于 java.util 包中,是一个用来存放对象的容器。
①、集合只能存放对象。比如你存一个 int 型数据 1放入集合中,其实它是自动转换成 Integer 类后存入的,Java中每一种基本类型都有对应的引用类型。
②、集合存放的是多个对象的引用,对象本身还是放在堆内存中。
③、集合可以存放不同类型,不限数量的数据类型。
Java 集合可分为 Set、List 和 Map 三种大体系
Set:无序、不可重复的集合
List:有序,可重复的集合
Map:具有映射关系的集合
HashSet
HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。我们大多数时候说的set集合指的都是HashSet
HashSet 具有以下特点:
不能保证元素的排列顺序(当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据 hashCode 值决定该对象在 HashSet 中的存储位置。
)
不可重复(如果两个元素的 equals() 方法返回 true,但它们的 hashCode() 返回值不相等,hashSet 将会把它们存储在不同的位置,但依然可以添加成功。
)
HashSet 不是线程安全的
集合元素可以是null
HashSet 集合判断两个元素相等的标准:两个对象通过 equals() 方法比较相等,并且两个对象的 hashCode() 方法返回值也相等。
如果两个对象通过 equals() 方法返回 true,这两个对象的 hashCode 值也应该相同。
如果想让集合只能存放同样类型的对象,使用泛型
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Test {
public static void main(String[] args) {
Set set =new HashSet();//等价于Set <Object> set=new HashSet<Object>();
set.add(1);
set.add(22);
set.add("2a2");
set.add("sss");
set.add("sad");
set.add(null);
set.remove(1);
System.out.println(set.contains(1));//判断是否有这个值
//set.clear(); //清空集合
System.out.println(set);
//使用迭代器遍历
Iterator it =set.iterator();
while(it.hasNext() ){
System.out.println(it.next());
}
//for each 迭代
for(Object obj:set)//把set的值每一个值取出来赋给obj,直到循环结束
{
System.out.println(obj);
}
//集合的大小
System.out.println(set.size());
//使用泛型
Set<String> set1 =new HashSet<String>();//指定String为集合的泛型,那么不能存放其他类型的数据
set1.add("ss");
}
}
TreeSet
TreeSet 是 SortedSet 接口的实现类,TreeSet 可以确保集合元素处于排序状态。
TreeSet 支持两种排序方法:自然排序和定制排序。默认情况下,TreeSet 采用自然排序
必须放入同样类的对象.(默认会进行排序) 否则可能会发生类型转换异常.我们可以使用泛型来进行限制
import java.util.Comparator;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
public class Test1 {
public static void main(String[] args) {
Set<Integer> set=new TreeSet<Integer>();
//TreeSet自然排序
set.add(5);
set.add(6);
set.add(7);
System.out.println(set);
set.contains(8);
//使用迭代器遍历
Iterator<Integer> it =set.iterator();
while(it.hasNext() ){
System.out.println(it.next());
}
//for each 迭代
for(Integer i:set)//把set的值每一个值取出来赋给i,直到循环结束
{
System.out.println(i);
}
}
}
定制排序,提供一个 Comparator 接口的实现类对象。由该 Comparator 对象负责集合元素的排序逻辑
import java.util.Comparator;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
public class Test1 {
public static void main(String[] args) {
Person p1=new Person("张三",23);
Person p2=new Person("李四",20);
Person p3=new Person("王五",21);
Person p4=new Person("马六",29);
Set<Person>set1 =new TreeSet<Person>(new Person());
set1.add(p1);
set1.add(p2);
set1.add(p3);
set1.add(p4);
for(Person p:set1) {
System.out.println(p.name+" "+p.age);
}
}
}
class Person implements Comparator<Person>{ //把person对象存到TreeSet中并按照年龄排序
int age;
String name;
public Person() { //为什么要写这个无参构造
}
public Person(String name,int age) {
this.name=name;
this.age=age;
}
@Override
public int compare(Person o1, Person o2) { //年龄正序排列
if(o1.age>o2.age) {
return 1;
}else if(o1.age<o2.age) {
return -1;
}else {
return 0;
}
}
}
List(接口)与ArrayList(类)
List 代表一个元素有序、且可重复的集合,集合中的每个元素都有其对应的顺序索引
List 允许使用重复元素,可以通过索引来访问指定位置的集合元素。
List 默认按元素的添加顺序设置元素的索引。
List 集合里添加了一些根据索引来操作集合元素的方法
import java.util.ArrayList;
import java.util.List;
public class Test5 {
public static void main(String[] args) {
List<String>list =new ArrayList<String>(); //list 是接口可以接受实现类的new对象
list.add("a"); //索引下标是0
list.add("c");
list.add("b");
list.add("d");
System.out.println(list.get(2)); //通过索引来访问指定位置元素
list.add(1,"f"); //在索引为1的位置插入数据
List<String> l =new ArrayList<String>();
l.add("123");
l.add("456");
list.addAll(2,l); //在指定位置插入集合
System.out.println(list);
System.out.println(list.indexOf("d")); //获取指定元素在集合中第一次出现的索引下标
System.out.println(list.lastIndexOf("d")); //获取指定元素在集合中最后一次出现的索引下标
list.remove(1);
list.set(2 ," ff"); //根据指定的索引下标修改元素
System.out.println(list);
List<String> sss=list.subList(0,2); //截取到0到2的元素存到集合sss中,不包含第2个
System.out.println(sss);
System.out.println(list.size());
}
}
ArrayList 和 Vector 是 List 接口的两个典型实现
区别:
Vector是一个古老的集合,通常建议使用 ArrayList
ArrayList 是线程不安全的,而 Vector 是线程安全的。
即使为保证 List 集合线程安全,也不推荐使用 Vector
Map集合
Map 用于保存具有映射关系的数据,因此 Map 集合里保存着两组值,一组值用于保存 Map 里的 Key,另外一组用于保存 Map 里的 Value
Map 中的 key 和 value 都可以是任何引用类型的数据
Map 中的 Key 不允许重复,即同一个 Map 对象的任何两个 Key 通过 equals 方法比较中返回 false
Key 和 Value 之间存在单向一对一关系,即通过指定的 Key 总能找到唯一的,确定的 Value。
Map 接口与HashMap类
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class Test2 {
public static void main(String[] args) {
Map<String, Integer> map =new HashMap<String, Integer>();
map.put("b", 1);
map.put("c", 3); //添加数据
map.put("d", 2);
System.out.println(map);
System.out.println(map.get("b")); //根据key取值
map.remove("c");
System.out.println(map.size());
System.out.println(map.containsKey("b"));//判断当前集合是否含有指定的key
System.out.println(map.containsValue(10));//判断当前集合是否含有指定的value
//map.clear();
//遍历map集合
Set <String> keys =map.keySet(); //获取map集合的key集合
map.values(); //获取map集合的value集合
for (String key:keys) {
System.out.println("key: "+ key +",value: "+map.get(key));
}
//map.entrySet()方法遍历;
Set<Entry<String, Integer>> entrys =map.entrySet();
for(Entry<String, Integer>en:entrys) {
System.out.println("key: "+ en.getKey() +",value: "+en.getValue());
}
}
}
HashMap 和 Hashtable 是 Map 接口的两个典型实现类
区别:
Hashtable 是一个古老的 Map 实现类,不建议使用
Hashtable 是一个线程安全的 Map 实现,但 HashMap 是线程不安全的。
Hashtable 不允许使用 null 作为 key 和 value,而 HashMap 可以
与 HashSet 集合不能保证元素的顺序一样,Hashtable 、HashMap 也不能保证其中 key-value 对的顺序
Hashtable 、HashMap 判断两个 Key 相等的标准是:两个 Key 通过 equals 方法返回 true,hashCode 值也相等。
Hashtable 、相等的标准是:两个 Value 通过 equalHashMap 判断两个 Values 方法返回 true
TreeMap
一般使用map集合不会使用复杂对象做key
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
public class Test2 {
public static void main(String[] args) {
//TreeMap 自然排队是字典排序
Map<Integer, String> map =new TreeMap<Integer, String>();
map.put(4,"s");
map.put(2,"ss");
map.put(1,"sq");
map.put(5,"st");
System.out.println(map);
Map<String, String> map1 =new TreeMap<String, String>();
map1.put("a", "1");
map1.put("b", "1");
map1.put("c", "1");
map1.put("d", "1");
System.out.println(map1);
}
}
操作集合的工具类:Collections
Collections 是一个操作 Set、List 和 Map 等集合的工具类
Collections 中提供了大量方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法
排序操作:
reverse(List):反转 List 中元素的顺序
shuffle(List):对 List 集合元素进行随机排序
sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Test3 {
public static void main(String[] args) {
List<String>list =new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("a");
System.out.println(list);
Collections.reverse(list); //反转集合
System.out.println(list);
Collections.shuffle(list); //随机排序
Collections.sort(list); //字典升序排列
Collections.swap(list,0,4); //将0 4位置的元素交换
System.out.println(list);
Collections.frequency(list,"a");//列表list中a元素出现的次数
Collections.replaceAll(list,"a","aa")//把a用aa替换
}
}
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Test3 {
public static void main(String[] args) {
Student s1 =new Student(14,"张三");
Student s2 =new Student(16,"李四");
Student s3 =new Student(11,"王五");
Student s4 =new Student(13,"马六");
List<Student> list =new ArrayList<Student>();
list.add(s1);
list.add(s2);
list.add(s3);
list.add(s4);
for(Student s:list) {
System.out.println(s.name+" , "+s.age);
}
Collections.sort(list,new Student()); //前面是列表名,后面是这个列表对应对象的类
System.out.println("----");
for(Student s:list) {
System.out.println(s.name+" , "+s.age);
}
}
}
//实现Comparator这个接口,泛型是Student
class Student implements Comparator<Student>{
int age;
String name;
public Student() {
}
public Student(int age,String name) {
this.age=age;
this.name=name;
}
@Override
public int compare(Student o1, Student o2) { //根据年龄升序排序
if(o1.age>o2.age) {
return 1;
}else if(o1.age<o2.age) {
return -1;
}else {
return 0;
}
}
}
同步控制
Collections 类中提供了多个 synchronizedXxx() 方法,该方法可使将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题