容器2
Java 集合主要有 3 种重要的类型:
List:是一个有序集合,可以放重复的数据
Set:是一个无序集合,不允许放重复的数据
Map:是一个无序集合,集合中包含一个键对象,一个值对象,键对象不允许重复,值对象可以重 复(身份证号—姓名)
List接口
List 接口下面主要有两个实现 ArrayList 和 LinkedList,他们都是有顺序的,也就是放进去 是什么顺序,取出来还是什么顺序,也就是基于线性存储,可以看作是一个可变数组
ArrayList:查询数据比较快,添加和删除数据比较慢(基于可变数组)
LinkedList:查询数据比较慢,添加和删除数据比较快(基于链表数据结构)
import java.util.*;
public class ArrayListTest01 {
public static void main(String[] args) {
//最好不要这样写,这样属于面向具体编程了
//无法达到灵活互换
//最好面向接口编程
ArrayList arrayList = new ArrayList();
//采用面向接口编程
//使用 Collection 会更灵活,如果 List 不能满足要求
//那么可以采用 HashSet,因为 HashSet 也实现了该接口
Collection c = new ArrayList();
//面向接口编程
//采用 list 接口可以使用 Collection 里的方法
//也可以使用 list 接口扩展的方法
List l = new ArrayList();
//自动装箱,适合于 jdk1.5
l.add(1);
l.add(3);
//jdk1.5 以前,必须如下使用
l.add(new Integer(2));
l.add(new Integer(4));
//可以加入重复数据
l.add(2);
//不能加入字符串
//在强制转换时会出现 ClassCastException 错误
//l.add("sadfdsfs");
//可以采用 List 接口的中 get()方法依次取得元素
//输出结果为,不会打乱顺序
/*
1
3
2
4
2
*/
for (int i=0; i<l.size(); i++) {
//将 Object 强制转换为 Integer
Integer e = (Integer)l.get(i);
System.out.println(e);
}
System.out.println("");
//调用 remove 删除集合中的元素
//如果元素重复会 remove 掉第一个匹配的
l.remove(2);
//采用 Iterator 遍历数据(while 循环)
//Iterator 是一种模式,主要可以统一数据结构的访问方式
//这样在程序中就不用关心各个数据结构的实现了
//使对不同数据结构的遍历更加简单了,更加统一了
Iterator iter = l.iterator();
while (iter.hasNext()) {
Integer v = (Integer)iter.next();
System.out.println(v);
}
System.out.println("");
//采用 Iterator 遍历数据(for 循环)
for (Iterator iter1=l.iterator(); iter1.hasNext();) {
Integer v = (Integer)iter1.next();
System.out.println(v);
}
//在集合中是否包含 3,输出为:true
System.out.println(l.contains(3));
//集合是否为空,输出:false
System.out.println(l.isEmpty());
System.out.println("");
//转换成对象数组
Object[] oArray1 = l.toArray();
for (int i=0; i<oArray1.length; i++) {
Integer v = (Integer)oArray1[i];
System.out.println(v);
}
System.out.println("");
//运行时自动创建相应类型的数组
Integer[] iArray = new Integer[l.size()];
l.toArray(iArray);
for (int i=0; i<iArray.length; i++) {
int v = iArray[i];
System.out.println(v);
}
}
}
LinkedList
用法跟ArrayList相同
import java.util.*;
public class LinkedListTest01 {
public static void main(String[] args) {
//最好不要这样写,这样属于面向具体编程了
//无法达到灵活互换
//最好面向接口编程
LinkedList arrayList = new LinkedList();
//采用面向接口编程
//使用 Collection 会更灵活,如果 List 不能满足要求
//那么可以采用 HashSet,因为 HashSet 也实现了该接口
Collection c = new LinkedList();
//面向接口编程
//采用 list 接口可以使用 Collection 里的方法
//也可以使用 list 接口扩展的方法
//List l = new ArrayList();
//因为 LinkedList 和 ArrayList 都实现了 List 接口,所以我们可以灵活互 换
//直接修改为 LinkedList,对我们的程序没有任何影响
List l = new LinkedList();
//自动装箱,适合于 jdk1.5
l.add(1);
l.add(3);
//jdk1.5 以前,必须如下使用
l.add(new Integer(2));
l.add(new Integer(4));
//可以加入重复数据
l.add(2);
for (int i=0; i<l.size(); i++) {
Integer e = (Integer)l.get(i);
System.out.println(e);
}
System.out.println("");
l.remove(2);
Iterator iter = l.iterator();
while (iter.hasNext()) {
Integer v = (Integer)iter.next();
System.out.println(v);
}
System.out.println("");
for (Iterator iter1=l.iterator(); iter1.hasNext();) {
Integer v = (Integer)iter1.next();
System.out.println(v);
}
System.out.println(l.contains(3));
System.out.println(l.isEmpty());
System.out.println("");
Object[] oArray1 = l.toArray();
for (int i=0; i<oArray1.length; i++) {
Integer v = (Integer)oArray1[i];
System.out.println(v);
}
System.out.println("");
Integer[] iArray = new Integer[l.size()];
l.toArray(iArray);
for (int i=0; i<iArray.length; i++) {
int v = iArray[i];
System.out.println(v);
}
}
}
HashSet实现类
import java.util.*;
public class LinkedListTest02 {
public static void main(String[] args) {
//采用面向接口编程
//使用 Collection 会更灵活,如果 List 不能满足要求
//那么可以采用 HashSet,因为 HashSet 也实现了该接口
//Collection c = new LinkedList();
//可以修改为 HashSet
Collection c = new HashSet();
//不能改为 HashSet,因为 HashSet 不是 List 产品
//List l = new HashSet();
//自动装箱,适合于 jdk1.5
c.add(1);
c.add(3);
//jdk1.5 以前,必须如下使用
c.add(new Integer(2));
c.add(new Integer(4));
//可以加入重复数据
c.add(2);
/*
for (int i=0; i<c.size(); i++) {
//不能采用 get,因为 get 是 List 接口扩展的
//父类不能看到子类扩展的功能
//反过来子类可以看到父类的功能,因为子类继承了父类
Integer e = (Integer)c.get(i);
System.out.println(e);
}
*/
System.out.println("");
Iterator iter = c.iterator();
while (iter.hasNext()) {
Integer v = (Integer)iter.next();
System.out.println(v);
}
System.out.println("");
for (Iterator iter1=c.iterator(); iter1.hasNext();) {
Integer v = (Integer)iter1.next();
System.out.println(v);
}
System.out.println(c.contains(3));
System.out.println(c.isEmpty());
System.out.println("");
Object[] oArray1 = c.toArray();
for (int i=0; i<oArray1.length; i++) {
Integer v = (Integer)oArray1[i];
System.out.println(v);
}
System.out.println("");
Integer[] iArray = new Integer[c.size()];
c.toArray(iArray);
for (int i=0; i<iArray.length; i++) {
int v = iArray[i];
System.out.println(v);
}
}
}
Set接口
HashSet
HashSet 中的数据是无序的不可重复的。HashSet 按照哈希算法存取数据的,具有非常好性能, 它的工作原理是这样的,当向 HashSet 中插入数据的时候,他会调用对象的 hashCode 得到该 对象的哈希码,然后根据哈希码计算出该对象插入到集合中的位置。
import java.util.*;
public class HashSetTest01 {
public static void main(String[] args) {
//它是无序的,不重复
Set set = new HashSet();
set.add("a");
set.add("b");
set.add("c");
//输出是无序的
for (Iterator iter=set.iterator(); iter.hasNext();) {
System.out.println(iter.next());
}
//加入重复数据
set.add("a");
System.out.println("");
for (Iterator iter=set.iterator(); iter.hasNext();) {
System.out.println(iter.next());
}
String s1 = "abc";
String s2 = "abc";
System.out.println("s1 equals s2 ," + s1.equals(s2));
//equals 相等,hashcode 一定是相等的
System.out.println("s1.hashCode=" + s1.hashCode());
System.out.println("s2.hashCode=" + s2.hashCode());
String s3 = "ddddd";
System.out.println("s1 equlas s3," + s1.equals(s3));
System.out.println("s3.hashCode=" + s3.hashCode());
}
}
TreeSet
TreeSet 可以对 Set 集合进行排序,默认自然排序(即升序),但也可以做客户化的排序
import java.util.*;
public class TreeSetTest01 {
public static void main(String[] args) {
Set set = new TreeSet();
set.add(9);
set.add(2);
set.add(5);
set.add(1);
//不能放入重复数据
set.add(5);
for (Iterator iter=set.iterator(); iter.hasNext();) {
Integer v = (Integer)iter.next();
System.out.println(v);
}
}
}
示例:对 Person 进行自然排序
import java.util.*;
public class TreeSetTest03 {
public static void main(String[] args) {
Person p1 = new Person();
p1.name = "张三";
p1.age = 20;
Person p2 = new Person();
p2.name = "李四";
p2.age = 30;
Person p3 = new Person();
p3.name = "张三";
p3.age = 40;
Set set = new TreeSet();
set.add(p1);
set.add(p2);
set.add(p3);
for (Iterator iter=set.iterator(); iter.hasNext();) {
Person p = (Person)iter.next();
System.out.println("name=" + p.name + ", age=" + p.age);
}
}
}
class Person {
String name;
int age;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GVGt3Vzq-1594304600302)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\1594303707803.png)]
出现错误,因为放到 TreeSet 中 TreeSet 会对其进行排序,那么必须实现 Comparable 接口,而 我们的 Person 没有实现,所以出现了错误,如:基本类型的包装类和 String 他们都是可以排 序的,他们都实现 Comparable 接口。
实现 Comparable 接口完成排序
import java.util.*;
public class TreeSetTest04 {
public static void main(String[] args) {
Person p1 = new Person();
p1.name = "张三";
p1.age = 20;
Person p3 = new Person();
p3.name = "张三";
p3.age = 40;
Person p2 = new Person();
p2.name = "李四";
p2.age = 30;
Set set = new TreeSet();
set.add(p1);
set.add(p2);
set.add(p3);
for (Iterator iter=set.iterator(); iter.hasNext();) {
Person p = (Person)iter.next();
System.out.println("name=" + p.name + ", age=" + p.age);
}
}
}
class Person implements Comparable {
String name;
int age;
//如果覆盖了 equals,最好保证 equals 和 compareto 在
//相等情况下的比较规则是一致的
public int compareTo(Object o) {
if (o instanceof Person) {
Person p = (Person)o;
//升序
//return (this.age - p.age);
//降序
return (p.age-this.age);
}
throw new IllegalArgumentException("非法参数,o=" + o);
}
}
实现 Comparator 接口完成排序
import java.util.*;
public class TreeSetTest05 {
public static void main(String[] args) {
Person p1 = new Person();
p1.name = "张三";
p1.age = 20;
Person p3 = new Person();
p3.name = "张三";
p3.age = 40;
Person p2 = new Person();
p2.name = "李四";
p2.age = 30;
Comparator personComparator = new PersonComparator();
Set set = new TreeSet(personComparator);
set.add(p1);
set.add(p2);
set.add(p3);
for (Iterator iter=set.iterator(); iter.hasNext();) {
Person p = (Person)iter.next();
System.out.println("name=" + p.name + ", age=" + p.age);
}
}
}
class Person {
String name;
int age;
}
//实现 Person 的比较器
//Comparator 和 Comparable 的区别?
//Comparable 是默认的比较接口,Comparable 和需要比较的对象紧密结合到一起 了
//Comparator 可以分离比较规则,所以它更具灵活性
class PersonComparator implements Comparator {
public int compare(Object o1, Object o2) {
if (!(o1 instanceof Person)) {
throw new IllegalArgumentException("非法参数,o1=" + o1);
}
if (!(o2 instanceof Person)) {
throw new IllegalArgumentException("非法参数,o2=" + o2);
}
Person p1 = (Person)o1;
Person p2 = (Person)o2;
return p1.age - p2.age;
}
}
采用匿名类完成 Comparator 的实现
import java.util.*;
public class TreeSetTest06 {
public static void main(String[] args) {
Person p1 = new Person();
p1.name = "张三";
p1.age = 20;
Person p3 = new Person();
p3.name = "张三";
p3.age = 40;
Person p2 = new Person();
p2.name = "李四";
p2.age = 30;
//采用匿名类实现比较器
Set set = new TreeSet(new Comparator() {
public int compare(Object o1, Object o2) {
if (!(o1 instanceof Person)) {
throw new IllegalArgumentException("非法参数,o1=" + o1);
}
if (!(o2 instanceof Person)) {
throw new IllegalArgumentException("非法参数,o2=" + o2);
}
Person p1 = (Person)o1;
Person p2 = (Person)o2;
return p1.age - p2.age;
}
}
);
set.add(p1);
set.add(p2);
set.add(p3);
for (Iterator iter=set.iterator(); iter.hasNext();) {
Person p = (Person)iter.next();
System.out.println("name=" + p.name + ", age=" + p.age);
}
}
}
class Person {
String name;
int age;
}
Comparable 和 Comparator 的区别?
一个类实现了 Camparable 接口则表明这个类的对象之间是可以相互比较的,这个类对象组成 的集合就可以直接使用 sort 方法排序。
Comparator 可以看成一种算法的实现,将算法和数据分离,Comparator 也可以在下面两种环境 下使用:
1、类的没有考虑到比较问题而没有实现 Comparable,可以通过 Comparator 来实现排序而不必 改变对象本身
2、可以使用多种排序标准,比如升序、降序等
Map接口
Map 中可以放置键值对,也就是每一个元素都包含键对象和值对象,Map 实现较常用的为 HashMap,HashMap 对键对象的存取和 HashSet 一样,仍然采用的是哈希算法,所以如果使用 自定类作为 Map 的键对象,必须复写 equals 和 hashCode 方法。
HashMap
import java.util.*;
public class HashMapTest01 {
public static void main(String[] args) {
Map map = new HashMap();
map.put("1001", "张三");
map.put("1002", "李四");
map.put("1003", "王五");
//采用 entrySet 遍历 Map
Set entrySet = map.entrySet();
for (Iterator iter=entrySet.iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry)iter.next();
System.out.println(entry.getKey() + ", " + entry.getValue());
}
System.out.println("");
//取得 map 中指定的 key
Object v = map.get("1003");
System.out.println("1003==" + v);
System.out.println("");
//如果存在相同的条目,会采用此条目替换
//但 map 中始终保持的是不重复的数据
//主要依靠 key 开判断是否重复,和 value 没有任何关系
map.put("1003", "赵柳");
//采用 keySet 和 get 取得 map 中的所有数据
for (Iterator iter=map.keySet().iterator(); iter.hasNext();) {
String k = (String)iter.next();
System.out.println(k + ", " + map.get(k));
}
}
}
map.put("1001", "张三");
map.put(“1002”, “李四”);
map.put(“1003”, “王五”);
//采用 entrySet 遍历 Map
Set entrySet = map.entrySet();
for (Iterator iter=entrySet.iterator(); iter.hasNext()😉 {
Map.Entry entry = (Map.Entry)iter.next();
System.out.println(entry.getKey() + ", " + entry.getValue());
}
System.out.println("");
//取得 map 中指定的 key
Object v = map.get(“1003”);
System.out.println(“1003==” + v);
System.out.println("");
//如果存在相同的条目,会采用此条目替换
//但 map 中始终保持的是不重复的数据
//主要依靠 key 开判断是否重复,和 value 没有任何关系
map.put(“1003”, “赵柳”);
//采用 keySet 和 get 取得 map 中的所有数据
for (Iterator iter=map.keySet().iterator(); iter.hasNext()😉 {
String k = (String)iter.next();
System.out.println(k + ", " + map.get(k));
}
}
}