1.集合出现的原因
集合的出现是为了优化数组的缺点(类型单一、长度固定、扩充复杂)
集合的特点:不限类型、不限数量
2.JavaBean
package Review.JavaCollections.Lists;
// JavaBean
public class Computer {
private String brand;
private int size;
private String color;
public Computer() {}
public Computer(String brand,int size,String color) {
this.brand = brand;
this.size = size;
this.color = color;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
JavaBean是用来做数据传递的,它是一个只有私有属性,属性对应的get/set方法,无参和全参的构造器的类
3.List
特点:元素可重复,有序
List是一个接口,常用的实现类AraayList
ArrayList继承了AbstractList并实现了List,然后AbstractList实现List。
1)创建方式
List list = new ArrayList();
2)常用方法
①add()、remove()、get()、set()
package Review.JavaCollections.Lists;
import java.util.ArrayList;
import java.util.List;
public class ListTest {
public static void main(String[] args) {
List list = new ArrayList();
list.add(1); // 16
list.add("abc"); // 2
Computer c = new Computer("lenovo",15,"black");
list.add(c); // 3
list.add(12.3); // 4
Object obj = list.get(0);
Object obj1 = list.get(1);
Object obj2 = list.get(2);
Object obj3 = list.get(3);
System.out.println(obj); // 输出第1个
System.out.println(obj1);
System.out.println(obj2);
System.out.println(obj3);
System.out.println("----分割线----");
list.remove(0); // 去掉第1个
obj = list.get(0);
System.out.println(obj);// 输出第1个
// list.remove(12.3); // 去掉12.3
list.set(0, "first"); // 在第一个插入“first”
obj = list.get(0);
System.out.println(obj); // 输出第1个
}
}
这里有一个要注意的地方:
list.add(123);
list.remove(123);
运行结果:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 123, Size: 4
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.remove(Unknown Source)
at Review.JavaCollections.Lists.ListTest.main(ListTest.java:45)
这里报了一个越界异常,这是因为remove()方法的参数是int类型,如果传入一个int类型,remove()会默认为是下标。
改进方法:
list.add(new Integer(123));
删除的话通过下标去删除。
②其他常用方法(类似String的方法)
3)泛型
4)集合的遍历
集合的遍历有三种:①for循环、②foreach循环、③迭代器
①for循环
package Review.JavaCollections.Lists;
import java.util.ArrayList;
import java.util.List;
public class ListCycle {
public static void main(String[] args) {
List<Computer> l = new ArrayList<Computer>();
Computer c = new Computer("hp",15,"blcak");
Computer c1 = new Computer("hp",15,"blcak");
Computer c2 = new Computer("hp",15,"blcak");
Computer c3 = new Computer("hp",15,"blcak");
Computer c4 = new Computer("hp",15,"blcak");
l.add(c);
l.add(c1);
l.add(c2);
l.add(c3);
l.add(c4);
for(int i=0;i<l.size();i++) {
Computer com = l.get(i);
System.out.println(com);
}
}
}
运行结果:
Computer [brand=hp, size=15, color=blcak]
Computer [brand=hp, size=15, color=blcak]
Computer [brand=hp, size=15, color=blcak]
Computer [brand=hp, size=15, color=blcak]
Computer [brand=hp, size=15, color=blcak]
②foreach循环
package Review.JavaCollections.Lists;
import java.util.ArrayList;
import java.util.List;
public class ListCycle {
public static void main(String[] args) {
List<Computer> l = new ArrayList<Computer>();
Computer c = new Computer("hp",15,"blcak");
Computer c1 = new Computer("hp",15,"blcak");
Computer c2 = new Computer("hp",15,"blcak");
Computer c3 = new Computer("hp",15,"blcak");
Computer c4 = new Computer("hp",15,"blcak");
l.add(c);
l.add(c1);
l.add(c2);
l.add(c3);
l.add(c4);
// for(每次遍历集合中的元素类型 当前元素赋值的变量:遍历对象)
for(Computer cc : l) {
System.out.println(cc);
}
}
}
运行结果:
Computer [brand=hp, size=15, color=blcak]
Computer [brand=hp, size=15, color=blcak]
Computer [brand=hp, size=15, color=blcak]
Computer [brand=hp, size=15, color=blcak]
Computer [brand=hp, size=15, color=blcak]
从上面代码中,可以看出for循环跟foreach循环输出的内容是一致的,但是在代码实现上,foreach循环要简洁明了得多。
③迭代器
package Review.JavaCollections.Lists;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ListCycle {
public static void main(String[] args) {
List<Computer> l = new ArrayList<Computer>();
Computer c = new Computer("hp",15,"blcak");
Computer c1 = new Computer("hp",15,"blcak");
Computer c2 = new Computer("hp",15,"blcak");
Computer c3 = new Computer("hp",15,"blcak");
Computer c4 = new Computer("hp",15,"blcak");
l.add(c);
l.add(c1);
l.add(c2);
l.add(c3);
l.add(c4);
Iterator<Computer> iter = l.iterator();
while(iter.hasNext()) {
Computer cc = iter.next();
System.out.println(cc);
}
}
}
运行结果:
Computer [brand=hp, size=15, color=blcak]
Computer [brand=hp, size=15, color=blcak]
Computer [brand=hp, size=15, color=blcak]
Computer [brand=hp, size=15, color=blcak]
Computer [brand=hp, size=15, color=blcak]
利用迭代器遍历集合,需要导入java.util.Iterator包,Iterator是一个接口,利用该接口下的两个方法hasNext() 和 next() 进行遍历输出。
hasNext():判断是否有下一个元素
next():指针往后移动一次后且返回当前元素
迭代器的源代码:
5)List的存储内容
List存放的是对象的引用地址。
6)集合排序
①对基本数据类型和String类型排序(排序默认是升序,自然顺序)
因为基本数据类型的包装类和String类实现了接口Comparable中的compareTo方法,直接通过Collections.sort(list)排序。
Integer的compareTo方法:
String的compareTo方法:
package Review.JavaCollections.Lists;
import java.util.*;
public class ListSortTest {
public static void main(String[] args) {
List<Integer> l = new ArrayList<Integer>();
l.add(123);
l.add(5);
l.add(350);
l.add(114);
l.add(204);
print(l);
System.out.println("-=-=-=-=-=-=-=-=-=-");
Collections.sort(l);
print(l);
Date date = new Date();
}
public static void print(List<Integer> l) {
for(Integer i : l) {
System.out.print(i+"\t");
}
System.out.println();
}
}
运行结果:
123 5 350 114 204
-=-=-=-=-=-=-=-=-=-
5 114 123 204 350
②对自定义对象排序
如果需要对自定义对象进行排序,则需在当前类里实现compareTo方法即可。
当前类:
package Review.JavaCollections.Lists;
public class Computer implements Comparable<Computer>{
private String brand;
private int size;
private String color;
public Computer() {}
public Computer(String brand,int size,String color) {
this.brand = brand;
this.size = size;
this.color = color;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Computer [brand=" + brand + ", size=" + size + ", color=" + color + "]";
}
@Override
public int compareTo(Computer c) {
return compare(this.size,c.size);
}
public int compare(int x,int y) {
return x < y ? -10 : ((x==y) ? 0 : 10);
}
}
测试类:
package Review.JavaCollections.Lists;
import java.util.*;
public class ListSortTest {
public static void main(String[] args) {
List list = new ArrayList();
Computer c = new Computer("hp",15,"blcak");
Computer c1 = new Computer("hp",17,"blcak");
Computer c2 = new Computer("hp",20,"blcak");
Computer c3 = new Computer("hp",11,"blcak");
Computer c4 = new Computer("hp",14,"blcak");
list.add(c);
list.add(c1);
list.add(c2);
list.add(c3);
list.add(c4);
print(list);
System.out.println("-=-=-=-=-=-=-=-=-=-");
/*a negative integer, zero, or a positive integer as this objectis less
than, equal to, or greater than the specified object.
小于、等于或大于指定对象的负整数、零或正整数。*/
Collections.sort(list);
print(list);
}
// 遍历输出集合
public static void print(List l) {
for(Object i : l) {
System.out.println(i+"\t");
}
}
}
运行结果:
Computer [brand=hp, size=15, color=blcak]
Computer [brand=hp, size=17, color=blcak]
Computer [brand=hp, size=20, color=blcak]
Computer [brand=hp, size=11, color=blcak]
Computer [brand=hp, size=14, color=blcak]
-=-=-=-=-=-=-=-=-=-
Computer [brand=hp, size=11, color=blcak]
Computer [brand=hp, size=14, color=blcak]
Computer [brand=hp, size=15, color=blcak]
Computer [brand=hp, size=17, color=blcak]
Computer [brand=hp, size=20, color=blcak]
对自定义对象排序时需要注意的几个问题:
①Comparable是一个接口,需要实现后才能使用, 比如:要对Computer这个对象的某个属性来排列显示时,Comparable被实现时需要在后面添加泛型如:类名 implements Comparable < Computer >。
②实现接口后要重写方法compareTo(只有一个参数)。
③如果比较的的数字,方法返回number-Object.number。
④如果比较的的字符串,方法返回string.equal(Object.string)。
⑤正常是按升序排列,在返回前面加个负号就可以降序排列。
如果在排序过程中,需要为对象的多个属性进行排序,怎么实现呢?
7)List接口实现的源代码
分析list的常用方法,通过ArrayList实现类来分析集合的实现方式
①创建接口对象
通过ArrayList()构造方法默认初始化了一个Object[10]数组,这就说明ArrayList底层是通过数组的方式来存放数据的。
②add(obj)
首先判断elementData这个数组是否能够存放当前元素,如果不够长,则需要扩充,默认扩充到原数组的1.5倍,把元素附加存入到elementData数组中,同时,size记录元素格式自增1,然后返回true
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!! 判断能否存放当前元素
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0) // 判断是否当前数组的长度是否能够存下当前元素
grow(minCapacity); // 如果长度不够,则扩充
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); // 此处默认扩充到1.5倍
if (newCapacity - minCapacity < 0) // 如果扩充1.5倍之后还是存不下,则直接扩充到自己想要的长度
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0) // 如果扩充到自己想要的长度后还不够,则赋值一个默认的最大长度
newCapacity = hugeCapacity(minCapacity); // 如果比默认最大值还不够,则把整数的最大值作为扩充的新长度:2的31次方-1
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
数组最大长度:
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;// ArrayList默认最大的长度是2的31次方-1-8
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
add(int,obj):把obj元素插入到int下标位置,数组元素往后移动
public void add(int index, E element) {
rangeCheckForAdd(index); // 判断是否符合插入要求,如果超出数组长度,则抛出异常
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
③ remove(index):根据下标删除元素类似数组中删除元素的方式
public E remove(int index) {
rangeCheck(index); // 判断移除元素的下表是否超出数组长度,如果超出数组长度,则抛出异常
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
return oldValue;
}
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
remove(obj):删除的是list中的第一个和obj相等的元素
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
}
④ get(index)
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
⑤ set(int,obj)
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
⑥ size()
public int size() {
return size;
}
8)List的其他实现类
实现类:Arraylist LinkedList vector
4.Set
元素不可重复,无序
1)Set集合的基本使用
① 创建set集合对象
② Set集合的常用方法(和List一致)
③ Set的遍历(因为Set中的元素是不可重复且是无序的,所以不能用for循环对其进行遍历)
Iterator \ for…each
④ Set泛型(使用和List一致)
⑤ Set中存放的是对象的引用地址
2)Set源码分析
3)Set的去重原理
4)Set的子接口
5.Map(映射)
特点:key–value键值对,根据key获取value值,key不能重复,value值可重复