集合初步认识
集合概述
-
集合是一种容器,用来装载其他元素,集合中只能存储引用(内存地址),不能存储基本数据类型,可以存储基本数据类型的包装类,集合中不能存储对象,只能存储对象的内存地址。
-
集合一共分为两大类,1:Collection集合,以单个元素方式存储。2:Map集合,以键值对方式存储。
Collection集合结构
-
在结构图中,Collection接口是Collection集合体系中父接口,其他的集合都继承Collection接口中的方法。
-
Collection接口继承Iterable接口,表示所有的集合都是可迭代的(可遍历的)。Iterable接口中有一个方法iterator()方法,这个方法可以返回一个Iterator对象(迭代器对象),通过Iterator对象两个方法hasNext()和next()可以完成集合的迭代(遍历)。
-
List集合存储元素的特点:有序可重复。有序表示集合元素有下标,存进去的顺序和取出来的顺序相同。可重复表示集合中可以存储相同元素。
-
Set集合存储元素的特点:无序不可重复。无序表示集合元素没有下标,存进去的顺序和取出来的顺序不同。不可重复表示集合中不可存储相同的元素。
-
ArrayList集合,底层是“数组”数据结构,线程非安全的。
-
LinkedList集合,底层是“双向链表”数据结构。
-
Vector集合,底层是”数组“数据结构,线程安全的。
-
HashSet集合,底层是HashMap集合,HashMap集合底层是“哈希表”数据结构。
-
TreeSet集合,底层是TreeMap集合,TreeMap集合底层是“二叉树”数据结构。
Collection接口中的常用方法
方法 | 解释 |
---|---|
boolean add(E e) | 向集合中添加元素 |
boolean addAll(Collection c) | 向集合中添加多个元素 |
void clear() | 清空集合 |
boolean contains(Object o) | 判断集合中是否包含元素o |
boolean isEmpty() | 判断集合中是否存在元素,返回true表示0元素,返回false表示>0元素 |
Iterator iterator() | 获取当前集合的迭代器对象 |
boolean remove(Object o) | 删除集合中元素o |
int size() | 获取集合中元素个数 |
Object[] toArray() | 将集合转成Object数组 |
public class Test {
public static void main(String[] args) {
// 创建集合
Collection collection = new ArrayList();
// 添加元素,这里的基本数据类型会自动装箱
collection.add(100);
collection.add(3.14);
collection.add("你好");
collection.add(true);
collection.add(new Object());
// 获取集合中元素个数
System.out.println("集合中的元素:" +collection.size());
// 删除元素
collection.remove(100);
System.out.println("集合中的元素:" +collection.size());
// 添加多个元素
Collection c1 = new ArrayList();
c1.add(1);
c1.add(2);
c1.add(3);
collection.addAll(c1);
System.out.println("集合中的元素:" +collection.size());
// 判断集合中是否包含元素3.14
System.out.println(collection.contains(3.14) ? "包含" : "不包含");
// 判断集合中是否存在元素,返回true表示0元素,返回false表示>0元素
System.out.println(collection.isEmpty());
// 将集合转成Object数组
Object[] objects = collection.toArray();
System.out.print("遍历数组:");
for (Object x : objects){
System.out.print(x +" ");
}
// 清空集合
collection.clear();
System.out.println("\n集合中的元素:" +collection.size());
}
}
运行结果:
集合中的元素:5
集合中的元素:4
集合中的元素:7
包含
false
遍历数组:3.14 你好 true java.lang.Object@74a14482 1 2 3
集合中的元素:0
-
这里研究 contains方法,判断集合中是否包含某个元素:
public class Test {
public static void main(String[] args) {
// 创建集合
Collection collection = new ArrayList();
// 添加元素
collection.add(new Integer(100));
collection.add(new Integer(200));
collection.add(new Integer(300));
// 创建一个Integer对象
Integer a = new Integer(300);
// 判断集合中是否包含a(a没有添加进集合中)
System.out.println(collection.contains(a));
}
}
运行结果:
true
-
这里发现运行结果是true。通过源代码得知,contains方法调用了indexOf方法,而indexOf调用了equals方法。集合在判断是否包含某个元素的时候,集合会拿自己集合中的每个元素和判断的元素进行equals进行比较,如果equals返回true,代表包含。
-
iterator()方法获取当前集合的迭代器对象,通过hasNext()和next()两个方法完成集合的元素迭代:
-
public class Test { public static void main(String[] args) { // 创建集合 Collection collection = new ArrayList(); // 添加元素 collection.add(100); collection.add(3.14); collection.add("你好"); collection.add(true); collection.add(new Object()); // 获取当前集合的迭代器对象,迭代器遍历方式是通用的,适合所以的Collection子类 Iterator iterator = collection.iterator(); /** * hasNext(),判断集合中是否还有元素可以迭代,如果返回true,表示集合中还有元素可迭代。 * next(),游标向前移动一位,将游标指向的元素取出,返回Object类型 */ while (iterator.hasNext()){ Object obj = iterator.next(); System.out.println(obj); } // 除了使用迭代器方式,还可以使用for循环遍历 for (Iterator it = collection.iterator();it.hasNext();){ Object obj = it.next(); System.out.println("for循环遍历:" +obj); } } } 运行结果: 100 3.14 你好 true java.lang.Object@74a14482 for循环遍历:100 for循环遍历:3.14 for循环遍历:你好 for循环遍历:true for循环遍历:java.lang.Object@74a14482
泛型
-
泛型是Java中一个非常重要的概念,在Java集合类框架中被广泛使用。
-
如何知道某个类型是否支持泛型,可以通过帮助文档查看。在帮助文档中出现类似:<E>,<F>,<T>...,只要带有<>的都表示支持泛型。泛型是给编译器参考的,泛型在编译阶段起作用,泛型指导编译器检查集合中的元素类型。
-
如何在在集合中取出元素都是String类型:
public class Test { public static void main(String[] args) { // 创建集合 Collection collection = new ArrayList(); // 添加元素 collection.add("zhangsan"); collection.add("lishi"); collection.add("wangwu"); // 获取迭代器对象 Iterator it = collection.iterator(); // 迭代集合 while (it.hasNext()){ /* 程序进行向下转型,如果父类不能转换为子类,结果抛出ClassCastException异常。 例如添加一个int类型元素,则此程序报错。 */ String s = (String)it.next(); System.out.println(s); } } }
-
JDK1.5推出新特性:泛型。使用泛型之后,编译器会自动检测next()方法返回值是String,不需要进行向下转型,避免了ClassCastException异常。对以上程序进行改造:
-
public class Test {
public static void main(String[] args) {
// 创建集合,使用泛型
Collection<String> collection = new ArrayList<String>();
// 这里只能添加String类型元素,不然编译器会报错
collection.add("100");
collection.add("lishi");
collection.add("wangwu");
// 获取迭代器对象
Iterator<String> it = collection.iterator();
// 迭代集合
while (it.hasNext()){
// 使用泛型之后,这里直接用String类型接收
String s = it.next();
System.out.println(s);
}
}
}
运行结果:;
100
lishi
wangwu
-
在Java7中推出一个新特性:自动类型推断。Java编译器会根据Collection<String>自动推断出ArrayList也是<String>。在Java7之后,后面的泛型类型的代码可以省略,由于<>长得像钻石,所以这种新特性又被称为钻石表达式。例如:
-
-
如何自定义泛型:
public class Test<随便写> { public static void main(String[] args) { // 创建对象 Test<String> test = new Test<>(); // 调用对象方法 test.show("hello"); } public void show(随便写 e){ System.out.println(e); } } 运行结果: hello
-
自定义泛型<>中的内容随便写,例如以上程序<>中内容是中文也可以运行(不建议使用中文),只要是一个合法标识符就行,这只是一个代号,是为指导编译器做类型检查。比如Test类使用的泛型是<String>,那么它的方法参数类型也必须是String类型。
-
使用for-each遍历Collection,for-each又叫做增强for循环,是JDK1.5新特性。例如:
/** for-each简单回顾 */ public class Test { public static void main(String[] args) { int[] arr = new int[]{1,2,3,4,5}; // 遍历数组 for (int x:arr){ System.out.println(x); } } } 运行结果: 1 2 3 4 5 /** 使用for-each遍历集合 */ public class Test { public static void main(String[] args) { // 创建集合 Collection<String> collection = new ArrayList<>(); // 添加元素 collection.add("张三"); collection.add("李四"); collection.add("王五"); // 遍历集合 for (String x : collection){ System.out.println(x); } } } 运行结果: 张三 李四 王五