集合
1.概述
集合类和数组不一样,数组元素即可以是基本类型的值,也可以是对象;而集合里只能保存对象(实际上只是保存对象的引用变量,但通常习惯上说是保存对象)
java 的集合类主要由两个接口派生而出:Collection和Map,是集合框架的根接口。
以上是Collection体系里的集合,其中粗线圈出的set和list接口分别代表了无序集合和有序集合;queue是队列实现;
Map实现类用于保存具有映射关系的数据。
2.Collection和Iterator接口
Collection接口是List、Set、Queue接口的父接口,有很多api以下给出一个例子
package cn.zack.eight.集合;
import java.util.*;
public class IteratorTest
{
public static void main(String[] args)
{
// 创建集合、添加元素的代码与前一个程序相同
Collection books = new HashSet();
books.add("轻量级Java EE企业应用实战");
books.add("疯狂Java讲义");
books.add("疯狂Android讲义");
// 获取books集合对应的迭代器
Iterator it = books.iterator();
while(it.hasNext())
{
// it.next()方法返回的数据类型是Object类型,因此需要强制类型转换
String book = (String)it.next();
System.out.println(book);
if (book.equals("疯狂Java讲义"))
{
// 从集合中删除上一次next方法返回的元素
it.remove();
}
// 对book变量赋值,不会改变集合元素本身
book = "测试字符串"; //①
}
System.out.println(books);
}
}
疯狂Android讲义
轻量级Java EE企业应用实战
疯狂Java讲义
[疯狂Android讲义, 轻量级Java EE企业应用实战]
Iterator仅用于遍历集合,本身不提供盛装对象的能力,如果需要创建Iterator对象,则必须有一个被迭代的集合,没有集合的Iterator仿佛无本之木,没有存在的价值。
3.使用Java8新增的Stream操作集合
简单示例
package cn.zack.eight.集合;
import java.util.Collection;
import java.util.HashSet;
public class CollectionStream {
public static void main(String[] args) {
// 创建books集合、为books集合添加元素的代码与8.2.5小节的程序相同。
Collection books = new HashSet();
books.add(new String("轻量级Java EE企业应用实战"));
books.add(new String("疯狂Java讲义"));
books.add(new String("疯狂iOS讲义"));
books.add(new String("疯狂Ajax讲义"));
books.add(new String("疯狂Android讲义"));
// 统计书名包含“疯狂”子串的图书数量
System.out.println(books.stream()
.filter(ele -> ((String) ele).contains("疯狂"))
.count()); // 输出4
// 统计书名包含“Java”子串的图书数量
System.out.println(books.stream()
.filter(ele -> ((String) ele).contains("Java"))
.count()); // 输出2
// 统计书名字符串长度大于10的图书数量
System.out.println(books.stream()
.filter(ele -> ((String) ele).length() > 10)
.count()); // 输出2
// 先调用Collection对象的stream()方法将集合转换为Stream,
// 再调用Stream的mapToInt()方法获取原有的Stream对应的IntStream
books.stream().mapToInt(ele -> ((String) ele).length())
// 调用forEach()方法遍历IntStream中每个元素
.forEach(System.out::println);// 输出8 11 16 7 8
}
}
可以看出,程序只要调用Collection的stream方法即可以返回该集合对象的Stream,接下来就可以通过Stream提供的方法对所有集合元素进行处理。
4.Set集合
类似一个罐子,可以依次把多个对象丢进set集合,而set通常不会记住元素的添加顺序。且set不允许包含重复元素,如果试图把两个相同元素放入则会返回false,新元素不会加入。
4.1HashSet类
package cn.zack.eight.集合;
import java.util.HashSet;
// 类A的equals方法总是返回true,但没有重写其hashCode()方法
class A {
@Override
public boolean equals(Object obj) {
return true;
}
}
// 类B的hashCode()方法总是返回1,但没有重写其equals()方法
class B {
@Override
public int hashCode() {
return 1;
}
}
// 类C的hashCode()方法总是返回2,且重写其equals()方法总是返回true
class C {
@Override
public int hashCode() {
return 2;
}
@Override
public boolean equals(Object obj) {
return true;
}
}
public class HashSetTest {
public static void main(String[] args) {
HashSet books = new HashSet();
// 分别向books集合中添加两个A对象,两个B对象,两个C对象
books.add(new A());
books.add(new A());
books.add(new B());
books.add(new B());
books.add(new C());
books.add(new C());
System.out.println(books);
}
}
[B@1, B@1, A@372f7a8d, C@2, A@4517d9a3]
4.2LinkedHashSet类
使用链表维护元素顺序,会按元素的添加顺序来访问集合的元素,因为要维护顺序,所以性能略低于HashSet。
package cn.zack.eight.集合;
import java.util.*;
public class LinkedHashSetTest
{
public static void main(String[] args)
{
LinkedHashSet books = new LinkedHashSet();
books.add("疯狂Java讲义");
books.add("轻量级Java EE企业应用实战");
System.out.println(books);
// 删除 疯狂Java讲义
books.remove("疯狂Java讲义");
// 重新添加 疯狂Java讲义
books.add("疯狂Java讲义");
System.out.println(books);
}
}
[疯狂Java讲义, 轻量级Java EE企业应用实战]
[轻量级Java EE企业应用实战, 疯狂Java讲义]
虽然 LinkedHashSet 使用了链表记录集合元素的添加顺序,但 LinkedHashSet 依然是
HashSet ,因此它依然不许集合元素重复
4.3TreeSet
TreeSet是 SortedSet 接口的实现类,正如 SortedSet 所暗示的,TreeSet 可以确保集合元素处于
排序状态
TreeSet 并不是根据元素的插入顺序进行排序的,而是根据元素实际值的大小来排序的。
HashSet 集合采用 hash 算法来决定元素的存储位置不 同,TreeSet 采用红黑树数据结构来存
合元素。
package cn.zack.eight.集合;
import java.util.*;
public class TreeSetTest
{
public static void main(String[] args)
{
TreeSet nums = new TreeSet();
// 向TreeSet中添加四个Integer对象
nums.add(5);
nums.add(2);
nums.add(10);
nums.add(-9);
// 输出集合元素,看到集合元素已经处于排序状态
System.out.println(nums);
// 输出集合里的第一个元素
System.out.println(nums.first()); // 输出-9
// 输出集合里的最后一个元素
System.out.println(nums.last()); // 输出10
// 返回小于4的子集,不包含4
System.out.println(nums.headSet(4)); // 输出[-9, 2]
// 返回大于5的子集,如果Set中包含5,子集中还包含5
System.out.println(nums.tailSet(5)); // 输出 [5, 10]
// 返回大于等于-3,小于4的子集。
System.out.println(nums.subSet(-3 , 4)); // 输出[2]
}
}
[-9, 2, 5, 10]
-9
10
[-9, 2]
[5, 10]
[2]
5.List集合
5.1ArrayList和Vector
都是有序的、元素可重复的集合,前者线性不安全(但是可以通过方法构造出线性安全)
后者线性安全,是JDK1.0很早实现的,很多重复的古老方法,且Stack是其子类【后进先出】的“栈”