一,集合类概述
1,List集合 2,Set集合
3,Map集合
4,Arrays类与Collections类
集合类概述
- Java.util包中提供了一些集合类,这些集合类又被称为容器。提到容器就会想到数组,它们的作用都是一样的,存储数据。
- 集合与数组的区别:
数组是一种集合,长度是固定的,储存同一种数据类型
集合只能存储对象,对象类型可以不一样的长度可变 - 集合类之间的关系如图:
List集合
- 概念:Collecttion接口是层次结构中的根接口,JDK 不提供此接口的任何直接 实现:它提供更具体的子接口(如 Set 和 List)实现。包 (bag) 或多集合 (multiset)(可能包含重复元素的无序 collection)应该直接实现此接口。
- List集合的特点:
- List集合包括List接口以及List接口的所有实现类。
- List集合中的元素允许重复,集合中的元素是有顺序的,各元素的顺序就是对象插入的顺序。
- 类似数组,可通过使用索引(元素在集合中的位置)来访问集合中的元素。
- List接口:List接口继承了Collection接口,因此包含Collection接口中的所有方法。此外,List接口中还定义了两个非常重要的方法。
get(int index):获得指定索引位置的元素。
set(int index, E element):将集合中指定索引位置的对象修改为指定的对象。
- List接口的实现类:List接口的常用实现类有ArrayList与LinkedList。
- ArrayList类实现了List接口,允许保存所有对象,包括null。
- 优点:可以根据索引位置对集合进行快速的随机访问。
- 缺点:向指定的索引位置插入对象或删除对象的速度较慢。
- LinkedList类采用链表结构保存。
优点:便于向集合中插入和删除对象。执行效率高。
缺点:随机访问集合中的对象时,效率较低。
- 泛型:为了指定确定的对象,防止在强制转换的过程中出现错误,增加安全性。
List<E> list = new ArrayList<E>();
List<E> list2 = new LinkedList<E>();
//上面的代码中,E就是泛型,可以写引用数据类型,不能写基本数据类型。
//例如:如果集合中的元素为字符串类型,那么E可以修改为String。
- List集合中常用的方法:
- add(E e):将指定的元素添加到此列表的尾部。E代表任何对象元素。返回值:boolean
- add(int index, E element):将指定的元素插入此列表中的指定位置。index:代表要插入的位置。E代表插入的元素。返回值:void
- addAll(Collection<? extends E> c):将另一个集合的所有元素加入到此集合的尾部。c代表另一个集合。返回值:boolean
- clear():移除此列表中的所有元素。返回值:void
- contains(Object o):如果此列表中包含指定的元素,则返回 true。返回值:boolean
- get(int index):返回此列表中指定位置上的元素。返回值:E
- indexOf(Object o):返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 -1。返回值:int
- isEmpty():如果此列表中没有元素,则返回 true。返回值:boolean
- lastIndexOf(Object o):返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 -1。返回值:int
- remove(int index):移除此列表中指定位置上的元素。返回值:E
- remove(Object o):移除此列表中首次出现的指定元素(如果存在)。返回值:boolean
- set(int index, E element):用指定的元素替代此列表中指定位置上的元素。返回值: E,泛型所指定的对象类型。
- size():返回此列表中的元素数。返回值: int
- 增强for循环:For-Each循环也叫增强型的for循环,或者叫foreach循环。
- 语法
//遍历数组
for(Type value : array){
//直接使用value
}
- 优缺点
- 优点:写法简单,便于使用
- 缺点:丢掉了索引信息。当遍历集合或数组时,如果需要访问集合或数组的下标,那么最好使用旧式的方式来实现循环或遍历,而不要使用增强的for循环,因为它丢失了下标信息。
Set集合
- Set集合的特点:
- 长度可变。
- 集合中的对象无序且不重复。
- 没有get(int index)方法获取元素,只能使用迭代器或者增强for循环。
- Set接口的主要实现类:HashSet类与TreeSet类
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("w");
set.add("o");
set.add("r");
set.add("l");
set.add("d");
//遍历set集合的方法
//方法一:
Iterator<String> iterable = set.iterator();//先将HashSet集合交给迭代器
System.out.print("iterable方式遍历HashSet集合:");
while(iterable.hasNext()){//迭代器判断是否有下一个元素
System.out.print(iterable.next()+" ");//获取下一个元素
}
//方法二:
System.out.print("\n"+"增强for循环方式遍历HashSet集合:");
for (String string : set) {
System.out.print(string+" ");
}
//使用treeSet遍历
Set<String> set2 = new TreeSet<String>();
set2.addAll(set);
System.out.print("\n"+"增强for循环方式遍历TreeSet集合:");
for (String string : set2) {
System.out.print(string+" ");
}
}
//执行结果
iterable方式遍历HashSet集合:r d w l o
增强for循环方式遍历HashSet集合:r d w l o
增强for循环方式遍历TreeSet集合:d l o r w
结论:两个类之间的主要区别是TreeSet集合会按照降序排序,而HashMap是无序的。按照阿斯克码排序。
TreeSet中的自然排序和定制排序
1,自然排序(实现Comparable接口,重写compareTo方法)
实体类:
public class Shop implements Comparable {
private String name;
private int price;
public Shop(String name, int price) {
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "name='" + name + '\'' + ", price=" + price;
}
@Override
public int compareTo(Object o) {
//排序按照商品的价格先按照商品从小到大排序,当商品价格一致按照商品的名字排序
if(o instanceof Shop){
Shop shop = (Shop) o;
if(this.price > shop.price){
return 1;
}else if(this.price < shop.price){
return -1;
}else{
return this.name.compareTo(shop.name);
}
}else {
throw new ClassCastException("类型有误");
}
}
}
测试类:
@Test
public void demo01(){
//自然排序
TreeSet<Shop> set = new TreeSet<>();
set.add(new Shop("香蕉",3));
set.add(new Shop("菠萝",7));
set.add(new Shop("草莓",40));
set.add(new Shop("西瓜",4));
set.add(new Shop("香梨",7));
for (Shop shop : set) {
System.out.println(shop);
}
}
2,定制排序,创建TreeSet时,向其中传入已经重写Comparator中方法的对象
实体类:
public class Shop{
private String name;
private int price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public Shop(String name, int price) {
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "name='" + name + '\'' + ", price=" + price;
}
}
测试类:
@Test
public void demo02(){
//定制排序
TreeSet set = new TreeSet<>(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
//排序按照商品的价格先按照商品从小到大排序,当商品价格一致按照商品的名字排序
if(o1 instanceof Shop && o2 instanceof Shop) {
Shop shop1 = (Shop)o1;
Shop shop2 = (Shop) o2;
if(shop1.getPrice() > shop2.getPrice()){
return 1;
}else if(shop1.getPrice() < shop2.getPrice()){
return -1;
}else{
return shop1.getName().compareTo(shop2.getName());
}
}else {
throw new ClassCastException("类型有误");
}
}
});
set.add(new Shop("香蕉",3));
set.add(new Shop("菠萝",7));
set.add(new Shop("草莓",40));
set.add(new Shop("西瓜",4));
set.add(new Shop("香梨",7));
for (Object shop : set) {
System.out.println(shop);
}
}
Map集合
- Map集合的特点:
- Map集合没有继承Collection接口,是一个单独的接口
- Map集合提供的是key到value的映射,即是一个键值对。一个键对应一个值。
- 一个Map集合中不能包含相同的key,后面相同的key的值会覆盖前面的相同key的值。
- 不同的key是可以有相同的值的。
- Map主要实现类:HashMap类与TreeMap类
- 类中的常用方法
- containsKey(Object key):如果此映射包含对于指定键的映射关系,则返回 true。
- containsValue(Object value):如果此映射将一个或多个键映射到指定值,则返回 true。
- get(Object key):返回指定键所映射的值;如果对于该键来说,此映射不包含任何映射关系,则返回 null。
- keySet():返回此映射中所包含的键的 Set 视图。
- put(K key, V value):在此映射中关联指定值与指定键。
- putAll(Map<? extends K,? extends V> m):将指定映射的所有映射关系复制到此映射中,这些映射关系将替换此映射目前针对指定映射中所有键的所有映射关系。
- remove(Object key):从此映射中移除指定键的映射关系(如果存在)。
- size():返回此映射中的键-值映射关系数。
- values():返回此映射所包含的值的 Collection 视图。
- 举例:
- 例1:
@Test
public void demo() {
Map<String, Object> map = new HashMap<String, Object>();//Map
map.put("admin", "123456");
map.put("lpm", "654321");
map.put("xxx", "aaa");
map.put("yyy", "bbb");
//遍历map集合的两种方法
//方法一:迭代器
//1.获取所有的key,并交给set集合
Set<String> set = map.keySet();
//2.直接遍历set集合
Iterator<String> iterator = set.iterator();
System.out.println("map集合包含key为admin吗:"+map.containsKey("admin")+
",map集合包含value为aaa吗:"+map.containsValue("aaa"));
System.out.println("TreeMap所打印的值:");
Map<String, Object> map1 = new TreeMap<String, Object>();
map1.putAll(map);
Set<String> set1 = map1.keySet();
Iterator<String> iterator1 = set1.iterator();
while(iterator1.hasNext()){
String key = iterator1.next();
Object value = map1.get(key);
System.out.println("key:"+key+",value:"+value);
}
}
//执行结果
map集合包含key为admin吗:true,map集合包含value为aaa吗:true
TreeMap所打印的值:
key:admin,value:123456
key:lpm,value:654321
key:xxx,value:aaa
key:yyy,value:bbb
结论:TreeMap会按照键key的降序排序。
Arrays类与Collections类
- 主要方法
- Arrays.sort(a):升序排序,其中a为数组
- Collections类中的常用方法
- reverse(List):反转List中元素的顺序
- shuffle(List):对List集合元素进行随机排序
- sort(List):根据元素的自然排序对指定List集合元素按升序排序
- sort(List, Comparator):根据指定的Comparator产生的顺序对List集合元素进行排序
- swap(List, int, int):将指定list集合中i处元素和j处元素进行交换
- Object max(Collection):根据元素的自然排序,返回给定集合中的最大元素
- Object max(Collection, Comparator):根据Comparator指定的顺序,返回给定集合中的最大元素
- Object min(Collection):根据元素的自然排序,返回给定集合中的最小元素
- Object max(Collection, Comparator):根据Comparator指定的顺序,返回给定集合中的最小元素
- int frequency((Collection, Object):返回指定集合中指定元素出现次数
- void copy(List dest, List src):将src中的内容复制到dest中
- boolean replaceAll(List list, Object oldVal, Object newVal):使用新值替换List对象中的所有旧值
写法:
List dest = Arrays.asList(new Object[list.size()]);
Collections.copy(dest,list)
Collections类
Collections类中提供了多个synchronizedXxx()方法,该方法可使将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题
说明:ArrayList和HashMap都是线程不安全的,如果程序要求线程安全,我们可以将ArrayList和HashMap转换为线程安全的,使用synchronizedList(List list)和synchronizedMap(Map map)