9.从零开始学习Java-集合

集合框架

//ArrayList、HashSet、HashMap、泛型

一、集合的概念

1.1 概念

对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能。

1.2 和数组区别

  • 数组长度固定,集合长度不固定
  • 数组可以存储基本类型和引用类型,集合只能存储引用类型

1.3 位置

java.util.*;

二、Collection体系集合

9.从零开始学习Java-集合_第1张图片

  • Collection:该体系结构的根接口,代表一组对象,称为“集合”。
  • List接口的特点:有下标、元素可重复。
  • Set接口的特点:无下标、元素不能重复。

2.1 Collection父接口

2.1.1 特点:

代表一组任意类型的对象,无序、无下标。

2.1.2 方法:

//查看API既可

//共性方法

  • boolean add(Object obj) //添加一个对象。
  • boolean addAll(Collection c) //将一个集合中的所有对象添加到此集合中。
  • void clear() //清空此集合中的所有对象。
  • boolean contains(Object o) //检查此集合中是否包含o对象
  • boolean equals(Object o) //比较此集合是否与指定对象相等。
  • boolean isEmpty() //判断此集合是否为空
  • boolean remove(Object o) //在此集合中移除o对象
  • int size() //返回此集合中的元素个数。
  • Object[] toArray() //将此集合转换成数组。

三、List接口与实现类

//列表集合(序列)

3.1 特点

有序、有下标、元素可以重复。

//允许满足e1.equals.(e2)重复。

3.2 方法

  • void add(int index, Object o) //在index位置插入对象o。
  • boolean addAll(int index, Collection c) //将一个集合中的元素添加到此集合中的 index位置。
  • Object get(int index) //返回集合中指定位置的元素。
  • List subList(int fromIndex, int toIndex) //返回fromIndex和toIndex之间的集合元素。

3.3 List实现类

  • ArrayList【重点】:

    //a.g.r.c方法

    //List接口的大小可变数组的实现。

    • 数组结构实现,查询快、增删慢;
    • JDK1.2版本,运行效率快、线程不安全。
    //JDK源码实现
        public boolean add(E e) {
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;//私有属性(数组)
            return true;
        }
    
    import java.util.ArrayList;
    public class TestArrayList {
        public static void main(String[] args){
            ArrayList arrayList = new ArrayList();
            arrayList.add("A");
            arrayList.add("B");
            arrayList.remove("B");
            arrayList.add(0, "D");
    //        arrayList.clear();//清空
            for (int i = 0; i < arrayList.size(); i++) {
                System.out.println(arrayList.get(i));
            }
            System.out.println(arrayList.size());
        }
    }
    
    
    import java.util.ArrayList;
    public class TestUserArrayList {
        public static void main(String[] args){
            ArrayList scores = new ArrayList();
            scores.add(99D);
            scores.add(98D);
            scores.add(95D);
            scores.add(97D);
            scores.add(99D);
            scores.add(91D);
            double sum = 0;
            for (int i = 0; i < scores.size(); i++) {
                sum += (Double) scores.get(i);
            }
            System.out.println(sum);
            System.out.println(sum/scores.size());
        }
    }
    
  • Vector:

    • 数组结构实现,查询快、增删慢;
    • JDK1.0版本,运行效率慢、线程安全。//加了synchronized锁。

    //早期版本,不太用。

    //JDK源码和arrayList差异
        public synchronized void copyInto(Object[] anArray) {//多了一个同步,需要排队,所以慢
            System.arraycopy(elementData, 0, anArray, 0, elementCount);
        }
    
  • LinkedList:

    • 链表结构实现,增删快,查询慢。

    //有一些first、last方法。//addFirst addLast

    //类LinkedList还有一些方法如peek()、peekFist()、pool()、poolLast()、pop()、push()等是实现自Queue父类,所以LinkedList不光属于List集合,也属于队列集合。

    import java.util.LinkedList;
    public class TestLinkedList {
        public static void main(String[] args){
            LinkedList linkedList = new LinkedList();
            linkedList.add("A");
            linkedList.add("B");
            linkedList.add(2,"C");
            linkedList.addFirst("D");
            for (int i = 0; i < linkedList.size(); i++) {
                System.out.println(linkedList.get(i));
            }
        }
    }
    

3.3.1 不同结构实现方式

ArrayList:必须开辟连续空间,查询快,增删慢。

LinkedList:无需开辟连续空间,查询慢,增删快。

3.3.2 ArrayList源码分析

  • DEFAULT_CAPACITY = 10;默认容量
  • 如果没有向集合中添加任何元素时,容量0,添加一个元素之后 容量10
  • 每次扩容大小是原来的1.5倍
  • elementData存放元素的数组
  • size 实际元素个数
  • add() 添加元素

3.3.3 数据结构:栈、队列

  • 栈:是一种先进后出的数据结构。
    • stack类:继承Vector类
    • push方法入栈、pop方法出栈
  • 队列:是一种先进先出的数据结构。
    • Queue接口:继承Collection接口
    • offer方法入队、pop方法出队
    • LinkedList实现了Queue接口

四、Set接口与实现类

4.1 Set子接口

4.1.1 特点:

无序、无下标、元素不可重复。

//还不保证该顺序恒久不变

4.1.2 方法:

全部继承自Collection中的方法。//14个

4.1.3 使用foreach循环遍历:

for(数据类型 局部变量 : 集合名){//iter
    //循环内部的局部变量,代表当次循环从集合中取出的对象 
}

4.2 Set实现类

  • HashSet【重点】: //基于hashMap的实现
    • 基于HashCode实现元素不重复。 //实现原理
    • 当存入元素的哈希码相同时,会调用==或equals进行确认,结果为true,拒绝后者存入。
  • LinkedHashSet:
    • 链表实现的HashSet,按照链表进行存储,即可保留元素的插入顺序。 //链表顺序
  • TreeSet: //基于hashMap的实现
    • 基于排列顺序实现元素不重复。 //排序顺序
    • 实现了SortedSet接口,对集合元素自动排序。 //必须实现java.lang.Comparable接口,重写compareTo的方法。
    • 元素对象的类型必须实现Comparable接口,指定排序规则。
    • 通过CompareTo方法确定是否为重复元素。
//HashSet
public class TestHashSet2 {

	public static void main(String[] args) {

		Student s1 = new Student("tom",20,"男",99D);
		Student s2 = new Student("jack",21,"男",97D);
		Student s3 = new Student("marry",20,"女",99D);
		Student s4 = new Student("annie",21,"女",100D);
		Student s5 = new Student("tom",20,"男",99D);
		
		HashSet<Student> students = new HashSet<Student>();
		
		students.add(s1);
		students.add(s2);
		students.add(s3);
		students.add(s4);
		//students.add(s1);//插入重复对象(地址重复)
		students.add(s5);//插入重复对象(地址不同、内容相同)
		
		for (Student stu : students) {
			System.out.println(stu);
			//System.out.println(stu.name.hashCode() +"\t"+ stu.age.hashCode() +"\t"+ stu.sex.hashCode() +"\t"+ stu.score.hashCode());
		}
		
		//System.out.println(s1.equals(s5));
		
	}

}

class Student{
	String name;
	Integer age;
	String sex;
	Double score;
	public Student() {
		super();
	}
	public Student(String name, Integer age, String sex, Double score) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
		this.score = score;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", sex=" + sex + ", score=" + score + "] " + this.hashCode();
	}
	
	@Override
	public int hashCode() {
		return this.name.hashCode() + this.age + this.sex.hashCode() + this.score.hashCode();
	}

	//触发条件:两个对象的哈希码相同,才执行equals
	@Override
	public boolean equals(Object obj) {
		
		System.out.println("---Student equals() Exected---");
		
		if(this == obj) return true;
		
		if(obj == null) return false;
		
		if(this.getClass() != obj.getClass()) return false;
		
		Student s = (Student)obj;

		if(this.name.equals(s.name) && this.age.equals(s.age) && this.sex.equals(s.sex) && this.score.equals(s.score))
			return true;
			
		return false;
	}	
}
public class TestLinkedHashSet {

	public static void main(String[] args) {

		//有序
		LinkedHashSet set = new LinkedHashSet();
		
		set.add("B");
		set.add("A");
		set.add("D");
		set.add("C");
		set.add("E");
		
		for(Object obj : set){
			System.out.println(obj);
		}	
	}
}
public class TestTreeSet {

	public static void main(String[] args) {
		
//		TreeSet set = new TreeSet();
//		
//		set.add("B");
//		set.add("A");
//		set.add("D");
//		set.add("C");
//		set.add("E");
//		
//		for(Object obj : set){
//			System.out.println(obj);
//		}
		
		//一组对象,必须是“可比较的”(必须实现java.lang.Comparable接口)
		TreeSet<Teacher> students = new TreeSet<Teacher>();
		
		students.add(new Teacher("tom",25,"男",5000D));
		students.add(new Teacher("jack",25,"男",5000D));
		students.add(new Teacher("annie",25,"女",5000D));
		students.add(new Teacher("vicky",25,"女",5000D));
		students.add(new Teacher("rose",25,"女",5000D));
		students.add(new Teacher("abby",25,"女",5000D));
		students.add(new Teacher("eric",25,"男",5000D));
				
		students.add(new Teacher("jack",25,"男",5000D));
		students.add(new Teacher("annie",25,"女",5000D));
		
		for (Teacher t : students) {
			System.out.println(t);
		}
		
	}

}
class Teacher implements Comparable<Teacher>{
	String name;
	int age;
	String sex;
	Double salary;
	
	public Teacher(String name, int age, String sex, Double salary) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
		this.salary = salary;
	}

	@Override
	public String toString() {
		return "Teacher [name=" + name + ", age=" + age + ", sex=" + sex
				+ ", salary=" + salary + "]";
	}


	@Override
	public int compareTo(Teacher o) {
		//工资多的靠后
		if(this.salary > o.salary){
			return 1;
		}else if(this.salary < o.salary){
			return -1;
		}else{
			//年龄大的靠后
			if(this.age > o.age){
				return 1;
			}else if(this.age < o.age){
				return -1;
			}else{
				//谁的名字首字母遵循字典排序
				if(this.name.compareTo(o.name) < 0){
					return -1;
				}else if(this.name.compareTo(o.name) > 0){
					return 1;
				}else{
					return this.sex.compareTo(o.sex);
				}
			}
		}
	}
}

4.3 数据结构:二叉排序树

  • 二叉排序树(Binary Sort Tree)
    • 又称二叉查找树(Binary Search Tree),亦称二叉搜索树。是数据结构中的一类。在一 般情况下,查询效率比链表结构要高。
  • 特点:
    • 若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
    • 若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
    • 左、右子树也分别为二叉排序树;
    • 没有键值相等的结点。

五、Map接口与实现类

5.1 Map结构

5.2 Map接口的特点

用于存储任意键值对(Key-Value)

  • 键:无下标、不可以重复(唯一)//代表假的值
  • 值:无下标、可以重复//代表真的值
  • Map接口与实现类

9.从零开始学习Java-集合_第2张图片

5.3 Map父接口

5.3.1 特点:

称为“映射”存储一对数据(Key-Value),键不可重复,值可以重复。

public class TestHashMap {
    public static void main(String[] args){
        HashMap<Integer,String> hashMap = new HashMap<Integer, String>();
        hashMap.put(0,"1");
        hashMap.put(1,"string");
        hashMap.put(2,"string2");
        hashMap.put(3,"string3");
        hashMap.put(4,"string4");
        hashMap.put(5,"string5");
        hashMap.put(6,"string6");

        String s = hashMap.remove(5);

        hashMap.put(0, "string0");//会对0键对应的值进行覆盖
        for (int i = 0; i < hashMap.size(); i++) {//key不是下标,不是连续的空间
            System.out.println(hashMap.get(i));
        }
        System.out.println("被移除的value为:"+s);
    }
}

5.3.2 方法:

  • V put(K key,V value) //将对象存入到集合中,关联键值。key重复则覆盖原值。
  • Object get(Object key) //根据键获取对应的值。
  • Set keySet()//返回所有key。
  • Collection values() //返回包含所有值的Collection集合。
  • Set> entrySet() //键值匹配的Set集合。
public class TestHashMapApply {

	public static void main(String[] args) {

		//中国 美国 韩国 意大利 日本 
		//String s = XXX.countries.get(null);
		//System.out.println(s);
		//所有键
		Set<String> keys = Country.countries.keySet();
		for (String k : keys) {
			//System.out.println(k);
		}
		
		//所有值
		Collection<String> values = Country.countries.values();
		for (String v : values) {
			//System.out.println(v);
		}	
		//所有键+值
		Set<Map.Entry<String,String>> entrys = Country.countries.entrySet();
		
		for (Map.Entry<String, String> entry : entrys) {
			//System.out.println(entry.getKey() +"\t"+ entry.getValue());
			System.out.println(entry);//即等同entry.toString方法
		}
		
		// & | >> << >>> ^ 
		
		//10 = 1010
		//7 =  0111
		//----------
//			   0010
		
		System.out.println(10 & 7);
	}
}

class Country{
	public static final Map<String , String> countries = new HashMap<String , String>();
	
	static{
		countries.put("CN","中华人民共和国");
		countries.put("US","美利坚合众国");
		countries.put("KR","韩国");
		countries.put("IT","意大利");
		countries.put("JP","日本");
		countries.put(null,null);
		countries.put("A",null);
		countries.put(null,"C");
	}
}

5.4 Map集合的实现类

  • HashMap【重点】:
    • JDK1.2版本,线程不安全,运行效率快 ;允许用null 作为key或是value。
  • Hashtable : //和hashMap用法相同
    • JDK1.0版本,线程安全,运行效率慢;不允许null作为key或是value。
  • Properties :
    • Hashtable的子类,要求key和value都是String。通常用于配置文件的读取。
  • TreeMap :
    • 实现了SortedMap接口(Map的子接口),可以对key自动排序,Key需实现 Comparable接口。

5.4.1 HashMap源码分析

  • HashMap刚创建时,table是null,为了节省空间,当添加第一个元素时,table容量 调整为16。
  • 当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍。目的是 减少调整元素的个数。
  • jdk1.8 当每个链表长度大于8,并且数组元素个数大于等于64时,会调整为红黑树,目 的提高执行效率。
  • jdk1.8 当链表长度小于6时,调整成链表。
  • jdk1.8以前,链表是头插入,jdk1.8以后是尾插入。

//Map的底层实现原理:Map就是一个链表数组,数组当中的每一个元素都是一个Map.entry对象,entry本身是一个链表节点,通过next指向下一个节点。

六、泛型集合与工具类

6.1 泛型:

6.1.1 概念:

Java泛型是JDK1.5中引入的一个新特性,其本质是参数化类型,把类型作 为参数传递。

常见形式有泛型类、泛型接口、泛型方法。

6.1.2 语法:

T称为类型占位符,表示一种引用类型。

6.1.3 好处:

提高代码的重用性

防止类型转换异常,提高代码的安全性

6.2 泛型集合

6.2.1 概念:

参数化类型、类型安全的集合,强制集合元素的类型必须一致。

import java.util.ArrayList;

public class TestGenericCollection {
    public static void main(String[] args){
        ArrayList<Double> list = new ArrayList<Double>();//泛型集合
        //原本不加泛型集合都可以往集合里面加

        list.add(10.0);
//        list.add(10);//报错
//        list.add("Hello");
//        list.add('A');
//        list.add(true);

        double sum = 0;
        for (int i = 0; i < list.size(); i++) {
            sum += list.get(i);
        }
    }
}
public class TestAdvencedGeneric {
    public static void main(String[] args){
        //实例泛型
        Myclass<Integer> mc = new Myclass<Integer>();
        mc.m1(111);
        Myclass<Double> mc2 = new Myclass<Double>();//后面的创建对象中的<>中的内容可以省略为<>
        mc2.m1(2.2);
        MyInterface<Byte> myInterface = new MyImplClass();//前面加后面不加
        myInterface.m2((byte)11);
        //静态泛型
        MyStaticClass.method();
        MyStaticClass.method1(123);//Integer
        MyStaticClass.method1(3.5);//Double
        MyStaticClass.method2(new Dog());
//        MyStaticClass.method2(new Cat());//不满足Comparable
//        MyStaticClass.method1("Hello");

    }
}
class MyStaticClass{
//    public static void method(E e){//不成立,因为静态方法在实例方法之前
//    }
public static void method() {
    }
    //不能在创建对象时完成,只能在方法调用时给予
    public static <T extends Number> void method1(T t){//泛型方法//与实例的差别
    System.out.println(t.getClass());
    //class java.lang.Integer
    //class java.lang.Double
    }
    public static <T extends Animal & Comparable> void method2(T t){//使用&来连接
        System.out.println(t.getClass());
        //class java0818.Dog
    }
}

abstract class Animal{
}

    class Dog extends Animal implements Comparable<Dog>{//泛型接口

        @Override
        public int compareTo(Dog o) {
            return 0;
        }
    }
    class Cat extends Animal{}


class Myclass<E>{
    public void m1(E e){

    }
}
interface MyInterface<T>{
    public void m2(T t);
}
class MyImplClass implements MyInterface<Byte>{
    @Override
    public void m2(Byte b) {

    }
}

6.2.2 特点:

  • 编译时即可检查,而非运行时抛出异常。
  • 访问时,不必类型转换(拆箱)。
  • 不同泛型之间引用不能相互赋值,泛型不存在多态。

6.3 Colletions工具类

6.3.1 概念:

集合工具类,定义了除了存取以外的集合常用方法。

6.3.2 方法:

  • public static void reverse(List list) //反转集合中元素的顺序
  • public static void shuffle(List list) //随机重置集合元素的顺序
  • public static void sort(List list) //升序排序(元素类型必须实现Comparable 接口)
//源码实现:
public static <T extends Comparable<? super T>> void sort(List<T> list) {
        list.sort(null);
    }

//整数类中默认实现了comparable接口,覆盖了compareTo方法
public final class Integer extends Number implements Comparable<Integer> 
public class TestCollections {
    public static void main(String[] args){
        List<Integer> list = new ArrayList<>();
        List<Integer> list2 = new ArrayList<>();
        list.add(1);
        list.add(3);
        list.add(5);
        list.add(7);
        list2.add(11);
        list2.add(1);
        list2.add(15);
        list2.add(12);
        Collections.reverse(list);//反转
        Collections.shuffle(list);//随机
        Collections.sort(list2);
        for (Integer integer1 : list) {
            System.out.println(integer1);
        }
        for (Integer integer2 : list2) {
            System.out.println(integer2);
        }
    }
}

七、总结:

集合的概念:

对象的容器,存储对象的对象,定义了对多个对象进行操作的常用方法。

List集合:

有下标、元素可以重复。(ArrayList、LinkedList、Vector)

Set集合:

无下标、元素不可重复。(HashSet、LinkedHashSet、TreeSet)

Map集合:

存储一对数据,键不可重复,值可重复。(HashMap、Hashtable、Properties、TreeMap)

Collections:

集合工具类,定义了除了存取以外的集合常用方法。

你可能感兴趣的:(从零开始学习Java-了解底层,JavaSE,java,数据结构,hashmap,queue)