一、List集合接口
package com.company.list;
/*
List集合储存元素特点:
1、有序(List集合中存储元素有下标)
2、可重复
*/
import java.util.*;
public class ListTest01 {
public static void main(String[] args) {
// 创建一个List集合
List l = new ArrayList();
// 添加
l.add(100);
l.add(90);
l.add(250);
l.add(250);
// 遍历
Iterator it = l.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
package com.company.list;
/*
深入List集合
ArrayList集合底层是数组。数组是有下标的,所以ArrayList集合有很多自己的特性。
ArrayList集合底层默认初始化容量是10,扩大之后的容量是原容量的1.5倍。
Vector集合底层默认容量也是10,扩大之后的容量是原容量的2倍。
LinkeList是链表,初始化容量就只有一个头节点
如何优化ArrayList和Vector?
尽量减少扩容操作,因为扩容需要数组拷贝。数组拷贝很耗内存。
一般推荐在创建集合的时候指定初始化容量。
List l = new ArrayList(50); // 初始化容量为50,如果不写就默认为10
*/
import java.util.*;
public class ListTest02 {
public static void main(String[] args) {
// 创建List集合
//List l = new ArrayList();
List l = new LinkedList();
// 这就是面向抽象编程的好处,ArrayList和LinkedList底层实现结构完全不一样
// 但是由于他们实现的都是List接口,里面都可以使用相同的方法
// 添加元素
l.add(123);
l.add(312);
l.add(69);
// 在下标为1的位置上添加555
l.add(1, 555);
// 取得第一个元素
System.out.println(l.get(0));
System.out.println("===========================");
// 遍历(List集合特有的遍历方式)
for(int i=0; i<l.size(); i++){
Object element = l.get(i);
System.out.println(element);
}
System.out.println("==========================");
// 迭代器也可以实现List集合遍历
Iterator it = l.iterator();
while(it.hasNext()){
Object element = it.next();
System.out.println(element);
}
}
}
二、Set集合接口
2.1 hashSet集合
package com.company.set;
/*
Set集合:HashSet
1、HashSet底层实际上是一个HashMap,HashMap底层采用了哈希表数据结构。
2、哈希表又叫做散列表,哈希表底层是一个数组,这个数组中每一个元素又是一个单向链表。
每一个单向链表都有独一无二的hash值,代表数组的下标。在某一个单向链表中的每一个节点
的hash值是相等的。hash值实际上是key调用hashCode方法,再通过“hash function”
转换成的值。
3、如何向哈希表中添加元素?
先调用被储存元素的key的hashCode方法,经过某个算法得出hash值,如果在这个哈
希表中不存在这个hash值,则直接加入元素。如果该hash值已经存在,继续调用key值之
间的equals方法,如果equals方法返回false,则将该元素添加。如果equals返回true,
则放弃添加该元素。
4、HashSet其实是HashMap中的key部分。HashSet有什么特点,HashMap中的key应该
有相同的特点。
5、HashMap和HashSet初始化容量都是16,默认加载因子是0.75(当存储的元素达到整个数组
的75%,就需要考虑扩容了)。
*/
import java.util.*;
public class SetTest01 {
public static void main(String[] args) {
// 创建Set集合
Set s = new HashSet();
// 无序不可重复
s.add(1);
s.add(100);
s.add(250);
s.add(88);
s.add(85);
s.add(1);
// 遍历
Iterator it = s.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
package com.company.set;
/*
关于往Set集合中存储的元素,该元素的hashCode和equals方法。
HashMap中有一个put方法,put(key, value) key是无序不可重复的。
结论:存储在HashSet集合或者HashMap集合key部分的元素,需要同时重写hashCode + equals方法
*/
import java.util.*;
public class SetTest02 {
public static void main(String[] args){
// 创建集合
Set s = new HashSet();
Employee e1 = new Employee("1000", "Jack");
Employee e2 = new Employee("1000", "Jack");
Employee e3 = new Employee("2000", "Tom");
Employee e4 = new Employee("2001", "King");
Employee e5 = new Employee("3000", "Tony");
Employee e6 = new Employee("3001", "Smith");
// 虽然e1和e2 no和name都一样,但是由于都是new的对象,内存地址肯定不一样。
// 在未重写hashCode()方法之前hash值肯定不同
System.out.println(e1.hashCode());
System.out.println(e2.hashCode());
// 添加元素
s.add(e1);
s.add(e2);
s.add(e3);
s.add(e4);
s.add(e5);
s.add(e6);
// 查看集合元素个数
// 尽管e1和e2内容完全一致,但是由于hash值不同,添加元素时仍作为两个不同元素,显然不符合业务逻辑。
// 因此需要重写Employee类中hashCode()方法
System.out.println(s.size());
}
}
// 根据现实的业务逻辑:该公司员工编号是:1000-9999
class Employee{
// 编号
String no;
// 姓名
String name;
// Constructor
public Employee(String no, String name){
this.name = name;
this.no = no;
}
// 重写equals方法
// 如果员工编号相同,并且名字相同,则是同一个对象
public boolean equals(Object o){
if(this==o){
return true;
}
if(o instanceof Employee){
Employee e = (Employee)o;
if(e.name.equals(this.name) && e.no.equals(this.no)){
return true;
}
}
return false;
}
// 重写hashCode方法
public int hashCode(){
// 以员工编号分组
// 可以根据员工编号1000~9999,进行均匀分组
// 例如1000~1999返回一个相同的hash值,2000~2999返回一个hash值...
// 这里就直接调用String重写之后的hashCode()方法
return no.hashCode();
}
}
2.2 SortedSet集合
package com.company.sortedSet;
/*
java.util.Set; 接口
java.util.SortedSet; 接口,存储元素无序不可重复,但是存进去的元素可以按照元素大小顺序自动排序。
java.util.TreeSet; 实现类
*/
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
public class SortedSetTest01{
public static void main(String[] args) throws ParseException{
// 创建元素
SortedSet ss = new TreeSet();
// 添加元素
ss.add(10); // 自动装箱
ss.add(8);
ss.add(78);
ss.add(56);
ss.add(24);
ss.add(63);
ss.add(9);
// 遍历
Iterator it = ss.iterator();
while (it.hasNext()) {
Object element = it.next();
System.out.println(element); // 8 9 10 24 56 63 78
}
// String
SortedSet strs = new TreeSet();
strs.add("Jack");
strs.add("Tom");
strs.add("Cook");
strs.add("Lucy");
strs.add("Zoom");
strs.add("Tony");
it = strs.iterator();
while (it.hasNext()) {
Object element = it.next();
System.out.println(element); // Cook Jack King Lucy Tom Tony
}
// 日期Date
String st1 = "2008-08-08";
String st2 = "2007-01-03";
String st3 = "2012-03-21";
String st4 = "2009-05-01";
String st5 = "2013-08-22";
String st6 = "2008-04-02";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date t1 = sdf.parse(st1);
Date t2 = sdf.parse(st2);
Date t3 = sdf.parse(st3);
Date t4 = sdf.parse(st4);
Date t5 = sdf.parse(st5);
Date t6 = sdf.parse(st6);
// 添加
SortedSet times = new TreeSet();
times.add(t1);
times.add(t2);
times.add(t3);
times.add(t4);
times.add(t5);
times.add(t6);
it = times.iterator();
while(it.hasNext()){
Object element = it.next();
System.out.println(element); // Wed Jan 03 00:00:00 CST 2007... 直接输出并不能满足格式要求
if(element instanceof Date){
Date d = (Date)element;
System.out.println(sdf.format(d)); // 2007-01-03... 也能按照从小到大排列
}
}
}
}
package com.company.sortedSet;
/*
前面一个java程序中,所使用的的三个类都是SUN提供的类
如果程序员直接定义类,然后存入TreeSet中,再遍历的时候,就会包错User cannot be cast to class java.lang.Comparable
这需要程序员在自己定义类的时候实现java.lang.Comparable接口
【注】SortedSet集合存储元素为什么可以自动排序?
因为被存储的元素实现了Compareable接口,SUN编写的TreeSet集合在添加元素的时候,
会调用compareTo方法完成比较。
*/
import java.util.*;
public class SortedSetTest02 {
public static void main(String[] args) {
SortedSet us = new TreeSet();
User u1 = new User("Jack", 25);
User u2 = new User("Tom", 18);
User u3 = new User("Tony", 23);
User u4 = new User("Andy", 27);
User u5 = new User("Bob", 20);
us.add(u1);
us.add(u2);
us.add(u3);
us.add(u4);
us.add(u5);
// 遍历
Iterator it = us.iterator();
while (it.hasNext()) {
Object element = it.next();
System.out.println(element); // User cannot be cast to class java.lang.Comparable
}
}
}
class User implements Comparable {
String name;
int age;
public User(String name, int age) {
this.age = age;
this.name = name;
}
public String toString() {
return "User[name = " + name + ",age = " + age + "]";
}
// 实现java.lang.Compareable;接口中的compareTo方法
// 该方法程序员负责实现,SUN提供的程序已经调用了该方法
// 需求1:按照User的age排序
/*
public int compareTo(Object o){
// 编写一个比较规则
int age1 = this.age;
int age2 = ((User)o).age;
return age1 - age2; // age1-age2 从小到大排列; age2-age1 从大到小排列
}
*/
// 需求2:按照User的name排序
public int compareTo(Object o) {
String name1 = this.name;
String name2 = ((User) o).name;
// 调用SUN公司在String类中写好的compareTo方法
return name1.compareTo(name2);
}
}
package com.company.sortedSet;
/*
让SortedSet集合做到排序的另一种方式: java.util.Comparator;
单独编写一个比较器
【注】现在已经讲述了SoretedSet排序的两种实现方法:
①在定义类的时候实现Comparable接口,重写compareTo()方法
②定义普通的类,然后单独编写一个类比较器,在创建TreeSet集合的时候,需要提供一个比较器
这两种方法有限石油第二种方法,因为它耦合度低,第一种方法定义的类必须实现Comparable接口,耦合度高。
SUN公司TreeSet源码,也是优先调用类比较器的。
*/
import java.util.*;
public class SortedSetTest03 {
public static void main(String[] args) {
// 创建TreeSet集合的时候提供一个比较器
SortedSet ps = new TreeSet(new ProductComparator());
Product p1 = new Product(8.88);
Product p2 = new Product(5.68);
Product p3 = new Product(6.42);
Product p4 = new Product(9.23);
Product p5 = new Product(8.21);
ps.add(p1);
ps.add(p2);
ps.add(p3);
ps.add(p4);
ps.add(p5);
Iterator it = ps.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
class Product{
double price;
Product(double price){
this.price = price;
}
public String toString(){
return "Product[price:" + price +"]";
}
}
// 单独编写一个比较器
class ProductComparator implements Comparator{
// 需求:按照商品价格排序
public int compare(Object o1, Object o2){
double price1 = ((Product)o1).price;
double price2 = ((Product)o2).price;
if(price1 == price2){
return 0;
}else if(price1 > price2){
return 1;
}else{
return -1;
}
}
}
/*
// 在创建集合时,也可以采用类名内部类的方式
// 匿名内部类:不推荐使用,因为比较器无法得到重复使用。
// 这种方法需要注意在创建是内部类必须是:new Comparator(){}
SortedSet ps = new TreeSet(new Comparator(){
public int compare(Object o1, Object o2){
double price1 = ((Product)o1).price;
double price2 = ((Product)o2).price;
if(price1 == price2){
return 0;
}else if(price1 > price2){
return 1;
}else{
return -1;
}
}
});
*