集合的引出
数组集合都是对多个数据进行储存操作的
数组特点:
1》长度一旦定义无法改变
2》数组类型声明,就只能储存此类型的数组
3》删除,增加效率比较低
4》储存有序,且可重复 >>>>>>>>>>>>>集合的了解
个个数据储存
ollection(接口)
{
List{ArrayList,LinkedList}
Set{HasSet,TreeSet}
}
对对储存
Map{
HasMap
TreeMap
}
collection
//创建对象:接口不能创建对象,利用实现类创建对象: Collection col = new ArrayList(); //调用方法:
//集合有一个特点:只能存放引用数据类型的数据,不能是基本数据类型 //基本数据类型自动装箱,对应包装类。int--->Integer //调用方法:
col.add(18);
List list = Arrays.asList(new Integer[]{11, 15, 3, 7, 1}); 数组转集合 col.addAll(list);//将另一个集合添加入col中
//col.clear();清空集合
System.out.println("集合中元素的数量为:" + col.size()); System.out.println("集合是否为空:" + col.isEmpty());
boolean isRemove = col.remove(15);//移除元素
System.out.println("是否包含元素:" + col3.contains(117));
对集合的遍历
//对集合遍历(对集合中元素进行查看)
//方式1:普通for循环
/*for(int i= 0;i<col.size();i++){
col.//不可以用普通for
}*/
//方式2:增强for循环
for(Object o:col){
System.out.println(o);
}
System.out.println("------------------------");
//方式3:iterator()
Iterator it = col.iterator();
while(it.hasNext()){//判断是否有下一个元素
System.out.println(it.next());
}
List
/* List接口中常用方法: 增加:add(int index, E element) 删除:remove(int index) remove(Object o) 修改:set(int index, E element) 查看:get(int index) 判断: */
ArrayList
//基于数组
List list = new ArrayList(); list.add(13); list.add(17);
list.add(3,66);// 下标为3的地方添加数据66
list.set(3,77);//修该下标为三的数据77
list.remove("abc");//移除元素"abc"
System.out.println(list.get(2));//查看下标为2的元素
//List集合 遍历: //方式1:普通for循环: System.out.println("---------------------"); for(int i = 0;i<list.size();i++){ System.out.println(list.get(i)); } //方式2:增强for循环: System.out.println("---------------------"); for(Object obj:list){ System.out.println(obj); } //方式3:迭代器: System.out.println("---------------------"); Iterator it = list.iterator(); while(it.hasNext()){ System.out.println(it.next()); }
ArrayList实现类 1.7
在jdk1.7中:调用构造器的时候给底层数组elementData初始化,数组长度为10
当10个位置满的时,数组开始扩容,是原数组的1.5倍
ArrayList实现类1.8
底层依旧是Object类型的数组。
ArrayList<Object>list= new ArrayList<>();//调用空构造器
调用构造器时候底层数组elementData初始化,数组长度0
ArrayList线程不安全
Vector实现类
底层Object数组
Vector ver = new Vector();
调用构造器底层数组elementDat初始化,数组长度10
底层扩容数组是原数组的2倍
Vector synchronized 线程安全
泛型
Collection<E>, List<E>, ArrayList<E> 这个<E>就是类型参数,即泛型。
泛型就是一个规则,规定集合储存数据的类型,如果没有泛型不方便数据的管理
jdk1.5后就开始使用泛型
)泛型实际就是 一个<>引起来的 参数类型,这个参数类型 具体在使用的时候才会确定具体的类型。
使用泛型可以确定集合储存数据的类型,编译器可以检查出来
后期翻遍遍历操作
都是引用数据类型,不能是基基本数据类型
ArrayList<String> list = new ArrayList<String>();
在jdk1.7后
ArrayList<String> list = new ArrayList<>(); //---钻石运算符
泛型的定义和实例化
//Test01普通类
Test01<W>泛型
public class Test01<W> { //普通类
int age;
String name;
W sex;
public void a(W n){
}
public void b(W[] m){
}
//这是main方法,程序的入口
public static void main(String[] args) {
//Test进行实例化:
//实例化的时候不指定泛型:
如果实例化的时候不明确的指定类的泛型,那么认为此泛型为Object类型
Test gt1 = new Test();
t1.a("abc");
t1.a(17);
t1.a(9.8);
t1.b(new String[]{1,2,34,54});
//(2)实例化的时候指定泛型:--->》推荐方式
Test<Integer> gt2 = new Test<>();
gt2.sex = 2;
gt2.a(1,3,6);
gt2.b(new iint[]{2,4,4,65});
//子类继承
class Test01 extends Test<Integer>{
}
class Test02<W> extends Test<W>{}
class Demo{
//这是main方法,程序的入口
public static void main(String[] args) {
//指定父类泛型,那么子类就不需要再指定泛型了,可以直接使用
Test01 sgt = new Test01();
sgt.a(19);
Test02<Integer> i1 = new Test02()<>;
i1.a(21);
}
}
LinkedList
基于双向链表
/* LinkedList常用方法: 增加 addFirst(E e) addLast(E e) offer(E e) offerFirst(E e) offerLast(E e) 删除 poll() pollFirst() pollLast() ---》JDK1.6以后新出的方法,提高了代码的健壮性 removeFirst() removeLast() 修改 查看 element() getFirst() getLast() indexOf(Object o) lastIndexOf(Object o) peek() peekFirst() peekLast() 判断 */
//创建一个LinkedList集合对象: LinkedList<String> list = new LinkedList<>(); list.add("aaaaa"); //
list.addLast("hh");//添加元素的头部 list.offer("kk");
//普通for循环: for(int i = 0;i<list.size();i++){ System.out.println(list.get(i)); } System.out.println("---------------------"); //增强for: for(String s:list){ System.out.println(s); } System.out.println("---------------------"); //迭代器: /*Iterator<String> it = list.iterator(); while(it.hasNext()){ System.out.println(it.next()); }*/ //下面这种方式好,节省内存 for(Iterator<String> it = list.iterator(); it.hasNext();){ System.out.println(it.next()); }
ArrayList与LinkedList的区别
ArrayList的实现是基于数组,LinkedList的实现基于双向链表
对于随机访问ArrayList优于LinkedList ArrayList直接根据对于元素的下标进行随机访问;
LinkedList每一个元素都依靠地址和他的最后一个元素连接在一起,查找某个元素比较复杂。
对于插入和删除 LinkedList优于ArrayList 因为元素添加到LnkedList任意位置的时候,不需要像ArrayList那样重新计算大小或者更新索引。
LnkedList比ArrayList更占内存 因为Linked的节点除了储存数据,还存储了两个索引,一个指前一个元素,一个指向后一个元素。
Set
HasSet
HashSet中不能有相同的元素,可以有一个Null元素,存入的元素是无序的。
HashSet底层数据结构是哈希表,
哈希表就是存储唯一系列的表,而哈希值是由对象的hashCode()方法生成。
确保唯一性的两个方法:hashCode()和equals()方法。
线程不安全
Integer数据类型
public static void main(String[] args) {
//创建一个HashSet集合:
HashSet<Integer> hs = new HashSet<>();
System.out.println(hs.add(19));//true
hs.add(5);
hs.add(20);
System.out.println(hs.add(19));//false 这个19没有放入到集合中
hs.add(41);
hs.add(0);
System.out.println(hs.size());//唯一,无序
System.out.println(hs);
}
String数据类型
public static void main(String[] args) {
//创建一个HashSet集合:
HashSet<String> hs = new HashSet<>();
hs.add("hello");
hs.add("apple");
hs.add("banana");
hs.add("html");
hs.add("apple");
hs.add("css");
System.out.println(hs.size());
System.out.println(hs);
}
LinkedHasSet
其实就是在HashSet的基础上,多了一个总的链表,这个总链表将放入的元素串在一起,方便有序的遍历:
底层原理=数组+链表=哈希表
LinkedHasSet 中不能有相同元素 可以null 按照放入顺序排列
底层结构由哈希表加链表组成
链表保证元素有序即储存和取出一致,哈希表保证元素的唯一性
线程不安全
//创建一个HashSet集合:
LinkedHashSet<Integer> hs = new LinkedHashSet<>();
System.out.println(hs.add(34));//true
hs.add(5);
hs.add(20);
System.out.println(hs.add(34));//false 这个19没有放入到集合中
hs.add(41);
hs.add(0);
System.out.println(hs.size());//唯一,无序
System.out.println(hs);
比较器
int
int a = 120;
int b = 120;
System.out.println(a-b); // =0 >0 <0
String类实现了Comparable接口,这个接口中有一个抽象方法compareTo,String类中重写这个方法即可
String a = "m";
String b = "B";
System.out.println(a.compareTo(b));
double
double a = 9.63;
double b = 129.3;
/* System.out.println((int)(a-b));*/强转后比较,味就不对了
System.out.println(((Double) a).compareTo((Double) b));
比较自定义的数据类型:
(1)内部比较器:
public class Student implements Comparable<Student>{ //实现Comparable
private int age;
private double height;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student(int age, double height, String name) {
this.age = age;
this.height = height;
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", height=" + height +
", name='" + name + '\'' +
'}';
}
@Override
public int compareTo(Student o) {
//按照年龄进行比较:
/*return this.getAge() - o.getAge();*/
//按照身高比较
/*return ((Double)(this.getHeight())).compareTo((Double)(o.getHeight()));*/
//按照名字比较:
return this.getName().compareTo(o.getName());
}
}
class Test{
//这是main方法,程序的入口
public static void main(String[] args) {
//比较两个学生:
Student s1 = new Student(132424,32160.5,"alili");
Student s2 = new Student(143244,1321370.5,"bnana");
System.out.println(s1.compareTo(s2));
}}
外部比较器
public class Student{
private int age;
private double height;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student(int age, double height, String name) {
this.age = age;
this.height = height;
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", height=" + height +
", name='" + name + '\'' +
'}';
}
}
class B1 implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
//比较年龄:
return o1.getAge()-o2.getAge();
}
}
class B2 implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
//比较姓名:
return o1.getName().compareTo(o2.getName());
}
}class B3 implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
//在年龄相同的情况下 比较身高 年龄不同比较年龄
if((o1.getAge()-o2.getAge())==0){
return ((Double)(o1.getHeight())).compareTo((Double)(o2.getHeight()));
}else{//年龄不一样
return o1.getAge()-o2.getAge();
}
}
}
public static void main(String[] args) {
//比较两个学生:
Student s1 = new Student(9,160.5,"alili");
Student s2 = new Student(14,170.5,"bnana");
//获取外部比较器:
Comparator bj1 = new B3();
System.out.println(bj1.compare(s1, s2));
}
外部比较器,多态扩展性好
TreeSet
不能有相同元素 不可以有null 根据元素的自然排序进行排序
底层数据结构是红黑树(一种自平衡二叉查找树)
线程不安全
//这是main方法,程序的入口
public static void main(String[] args) {
//创建一个TreeSet:
TreeSet<Integer> ts = new TreeSet<>();
ts.add(16762);
ts.add(376);
System.out.println(ts.size());//长度
System.out.println(ts);
}
特点:唯一,无序(没有按照输入顺序进行输出), 有序(按照升序进行遍历)
//底层原理
collection结构图
总结{
三者保证了元素的唯一性,
无排序要求可以选HasSet;
取出放入顺序相同可用LinkedHasSet ,
插入删除即排序或按照一定的规则排序可用TreeSet
}
Map
常用方法
/* 增加:put(K key, V value) 删除:clear() remove(Object key) 修改: 查看:entrySet() get(Object key) keySet() size() values() 判断:containsKey(Object key) containsValue(Object value) equals(Object o) isEmpty() */ //创建一个Map集合:无序,唯一 Map<String,Integer> map = new HashMap<>();
TreeMap
HashMap的key值是无序的,而实现了SortedMap接口的具体实现类TreeMap会对key值进行排序
TreeMap底层基于红黑树
TreeMap实现排序有两种方式
传入的key值实现了Comparable接口
创建TreeMap集合的时候指定比较器Comparator
Map的结构图
Map集合的特点
将键映射到值的对象
key和value是任意数据类型
一个映射不能包含重复的键{kei不能重复}
每个键只有一个key value 每个值有多个不同的键
HasMap
- key值不可重复
- 不保证插入顺序,但是打印结果,循环遍历时,输出顺序不会
LinkedHashMap
- 实现了Map接口,底层是依赖于哈希表和链表的,具有可预知的遍历顺序
- 哈希表保证唯一性,保证的是Key的唯一性
- 链表保证有序,保证的是键的有序(存储和取出顺序一致)