0
点赞
收藏
分享

微信扫一扫

集合Collection

飞鸟不急 2022-01-28 阅读 108

集合Collection

1、数组与集合

/*

1.集合与数组存储数据概述:
集合、数组都是对多个数据进行存储操作的结构,简称ava容器
说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt,.jpg,.avi,数据库中)

2.数组存储的特点:
>一旦初始化以后,其长度就确定了。
〉数组一旦定义好,其元素的类型也就确定了。我们也就只能操作指定类型的数据了。*
比如: String[]arr;int[]arr1;object[] arr2;


3.数组存储的弊端:
>一旦初始化以后,其长度就不可修改。
〉数组中提供的方法非常限,对于添加、删除、插入数据等操作,非常不便,同时效率不高。
〉获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用
〉数组存储数据的特点:序、可重复。对于无序、不可重复的需求,不能满足。


4.集合存储的优点:
解决数组存储数据方面的弊端。

 */

2、Collection接口

1.collection集合框架结构

/*
1.单列集合框架结构
collection接口:单列集台用来存储一个一个的对象
----List接口:存储序的、可重复的数据。-->“动态”数组
----ArrayList、LinkedList、Vector
----Set接口:存储无序的、不可重复的数据——>高中讲的"集合”
----HashSet、 LinkedHashSet、 TreeSet
*/

2.collection接口常用方法:

1.常用方法一:

/*
常用方法一:
    1.add()    增加
    2.addAll()     增加所有
    3.size()     大小
    4.clear()     清理
    5.isEmpty()   是否为空
   */


//collection接口常用方法一:
    @Test
    public  void collect1(){
        Collection collection=new ArrayList ();

        //add()    增加
        collection.add("AA");
        collection.add (123);
        collection.add ("BB");


        //addAll()     增加所有
        Collection collection1=new ArrayList ();
        collection1.add (456);
        collection.addAll (collection1);

        //size()     大小
        System.out.println (collection.size ());   //4

        //clear()     清理
        collection1.clear ();


        //isEmpty()   是否为空
        System.out.println (collection.isEmpty ());  // false
        System.out.println (collection1.isEmpty ());  //true
    }

2.常用方法二:

//collection接口常用方法二:
/*
1.contains(0bject obj):
判断当前集合中是否包含obj我们在判断时会调用obi对象所在类的equals().

2.containsAlL(collection coll):
判断形参coll1中的所有元素是否都存在于当前集合中e
*/
@Test
    public void collect2(){
Collection collect=new ArrayList ();
collect.add(123);
collect.add("FF");
collect.add(new Date ());

//1.contains(0bject obj):
// 判断当前集合中是否包含obj我们在判断时会调用obi对象所在类的equals().
    System.out.println (collect.contains (123));//true

    //2.containsAlL(collection coll):
    // 判断形参coll1中的所有元素是否都存在于当前集合中e
    Collection collect2=new ArrayList ();
    collect2.add("FF");
    System.out.println (collect.containsAll (collect2));//true

}

3.常用方法三:

 //collection接口常用方法三:
/*
1.remove(Object o)  删除
2.removeAll(Collection collection)   两个集合的差集
3.retainAll(Collection collection)  两个集合的交集
4.equals(Object o)  判断是否相等,存在有序
*/
    @Test
    public  void test3(){
        Collection collection=new ArrayList ();
        collection.add("AA");
        collection.add (123);
        collection.add ("BB");
        collection.add(456);

        //remove(Object o)  删除
        collection.remove (123);
        System.out.println (collection);

        //removeAll(Collection collection)   两个集合的差集
        Collection collect1= Arrays.asList ("AA",456);
        collection.removeAll (collect1);
        System.out.println (collection);

    }
    @Test
    public void test44(){
        Collection collection=new ArrayList ();
        collection.add("AA");
        collection.add (123);
        collection.add ("BB");
        collection.add(456);
        Collection collect1= Arrays.asList ("AA",456);

        //retainAll(Collection collection)  两个集合的交集
        collection.retainAll (collect1);
        System.out.println (collection);

        //equals(Object o)  判断是否相等,存在有序
        System.out.println (collection.equals (collect1));
    }

4.常用方法四:

  //collection接口常用方法四:
/*
1.hashCode() 返回当前对象的哈希值
2.toArray()    集合——>数组
3.Arrays.asList() 数组——>集合
*/
    @Test
    public  void test4(){
        Collection collection=new ArrayList ();
        collection.add("AA");
        collection.add (123);
        collection.add ("BB");
        collection.add(456);

        //hashCode() 返回当前对象的哈希值
        System.out.println (collection.hashCode ());

        //toArray()    集合——>数组
        Object[] objects = collection.toArray ();
        for(int i=0;i<objects.length;i++){
            System.out.println (objects[i]);
        }


        //Arrays.asList() 数组——>集合
        List<String> strings = Arrays.asList (new String []{"YY", "FF"});
        System.out.println (strings);

        //注意:
//         List<int[]> list = Arrays.asList (new int[]{123, 111});// 输出为[[I@5891e32e]
//        System.out.println (list.size ());//此时默认长度为1
        List<Integer> list1 = Arrays.asList (new Integer[]{123, 234});//输出为[123, 234]
        System.out.println (list1);
        System.out.println (list1.size ());//此时默认长度为2
    }

3、Iterator接口遍历集合元素

/*
集合元素的遍历操作:迭代器Iterator接口
1.内部的方法: 
      hasNext()
      next()
2.集合对象每次调用iterator()方法都得到一个全新的迭代器对象,
默认游标都在集合的第一个元素之前。
3.内部定义了remove(),可以在遍历的时候,删除集合中的元素。此方法不同于集合直接调用remove()

 */
@Test
    public void test(){
        Collection collection=new ArrayList ();
        collection.add("AA");
        collection.add (123);
        collection.add ("BB");
        collection.add(456);

       java.util.Iterator iterator = collection.iterator ();

        //遍历此集合中的所有元素————>三选一,不能同时运行
        //next () 遍历集合中的元素
        //方式一:若要遍历集合中的所有的,则需要重复操作   不推荐
        System.out.println (iterator.next ());//AA
        System.out.println (iterator.next ());//123
        System.out.println (iterator.next ());//BB
        System.out.println (iterator.next ());//456
        System.out.println ("************");

        //方式二:   for循环+iterator.next ()   不推荐
        for(int i=0;i<collection.size ();i++){
            System.out.println (iterator.next ());
        } 
        System.out.println ("************");

        //方式三:iterator.hasNext ()+iterator.next ()  推荐
        while(iterator.hasNext ()){
            System.out.println (iterator.next ());
        }
        
 //错误写法一:类似于指针,不能用非空判断  NoSuchElementException
//        while(iterator.next ()!=null){
//            System.out.println (iterator.next ());
//        }
//
//        //错误写法二:重复输出集合中的第一个元素
// //       集合对象每次调用iterator()方法都得到一个全新的迭代器对象,
    默认游标都在集合的第一个元素之前。
//        while(collection.iterator ().hasNext ()){
//            System.out.println (collection.iterator ().next ());
//        }
    }

    @Test
    public  void test5(){
        Collection collection=new ArrayList ();
        collection.add("AA");
        collection.add (123);
        collection.add ("BB");
        collection.add(456);

        java.util.Iterator iterator = collection.iterator ();

        while(iterator.hasNext ()){
                Object obj = iterator.next ();
                 if("BB".equals (obj)){
                  /*
                  remove()移除
                  如果还未调用next()或在上一次调用next方法之后已经调用了remove方法,
                  再调用remove都会报ILegalStateException。
                      */
                iterator.remove ();
            }
        }
        java.util.Iterator iterator1 = collection.iterator ();
        while(iterator1.hasNext ()){
            System.out.println (iterator1.next ());
            }
        }
    

4、forEach循环遍历

        @Test
    public  void test6(){
            Collection collection=new ArrayList ();
            collection.add("AA");
            collection.add (123);
            collection.add ("BB");
            collection.add(456);

             // for (集合类型  参数名 :集合名 )
            for (Object o:collection
                 ) {
                System.out.println (o);
            }
            System.out.println ("**************");


            //数组的循环遍历
            // for (数组类型  参数名 :数组名 )
            String[] arr=new String[]{"YY","FF"};
            for (String s: arr
                 ) {
                System.out.println (s);
            }
            System.out.println ("************");


            //测试题:
            // forEach循环的遍历跟for循环遍历
            String[] strings=new String[]{"FF","FF"};
            for (String s: strings
            ) {
               s="YY";
            }

            for (String s: strings
            ) {
                //forEach循环的遍历,不改变其原本的元素,因为 s="YY";这里的s只是参数名
                System.out.println (s);
            }
            System.out.println ("_______________");
            String[] string=new String[]{"FF","FF"};
           for(int i=0;i<string.length;i++){
               string[i]="YY";
           }
            for (String s: string
            ) {
                //for循环的遍历,改变其原本的元素,因为   string[i]="YY";
                System.out.println (s);
            }
        }

5、Collection子接口

1. List接口

1. list框架

/*
List接口框架
collection接口:单列集合,用来存储一个一个的对象
----List接口:存储有序的、可重复的数据。
               “动态数组,替换原有的数组
     ----ArrayList:作为List接口的主要实现类;线程不安全的,效率高;
              底层使用Object[] elementData存储
      ----LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高;
              底层使用双向链表存储
      ----Vector:作为List接口的古老实现类;线程安全的,效率低;
               底层使用Object[] elementData存储

面试题:ArrayList、 LinkedList、Vector三者的异同?
同:三个类都是实现了List接口,存储数据的特点相同:存储有序的、可重复的数据
不同:见上

 */

2.ArrayList的源码分析:

/*
ArrayList的源码分析:
1.  在jdk 7情况下
ArrayList list = new ArrayList();//底层创建了长度是10的object[]数组elementDataList.add(123);//eLementData[e] = new Integer(123);
...
list.add(11);//如果此次的添加导致底层elementData数组容量不够,则扩容。
默认情况下,扩容为原来的容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中。

结论:建议开发中使用带参的构造器:ArrayList list = new ArrayList(int capacity)

2.  在jdk 8情况下
ArrayList list = new ArrayList();//底层object[] elementData初始化为{}.并没有创建
list.add(123);//第一次调用add()时,底层才创建了长度10的数组,并将数据123添加到eleme...
后续的添加和扩容操作与jdk 7无异。

3小结: jdk7中的ArrayList的对象的创建类似于单例的饿汉式,
而jdk8中的ArrayList的对象的创建类似于单例的懒汉式,
延迟了数组的创建,节省内存。
*/

3.LinkedList的源码分析:

/*
3.LinkedList的源码分析:
LinkedList list = new LinkedList();内部声明了Node类型的first和Last属性,默认值为null
list.add(123);//将123封装到Node中,创建了Node对象
其中,Node定义为:体现了LinkedList的双向链表的说法
*/

4. Vector的源码分析:

/*
Vector的源码分析:
jdk7和jdk8中通过Vector()构造器创建对象时,底层都创建了长度为10的数组
在扩容方面,默认扩容为原来的数组长度的2倍。
*/

5. 常用方法:

/*
list常用方法
void add(int index, object ele):在index位置插入eLe元素
boolean addALll(int index, Collection eLes):从index位置开始将eLes中的所有元素添加进来object get(int index):获取指定index位置的元素
int indexOf(object obj):返回obj在集合中首次出现的位置
int lastIndex0f(Object obj):返回obj在当前集合中末次出现的位置
object remove(int index):移除指定index位置的元素,并返回此元素
object set(int index, object ele):设置指定index位置的元素为ele
list sublist(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合

 */
/*
总结:常用方法
增: add(object obj)
删: remove(int index) / remove(object obj)
改: set(int index,object ele)
查: get(int index)
插: add(int index,object ele)长度: size()
遍历: ①Iterator迭代器方式
      ②增强for循环
      ③普通的循环
 */
/*
注意:
区分List中remove(int index)和remove(Object obj)
 */
@Test
    public  void test(){
    ArrayList  list =new ArrayList ();
    list.add(123);
    list.add(456);
    list.add("BB");
    list.add(456);
    System.out.println (list);
    System.out.println ("***********");
//    void add(int index, object ele):在index位置插入eLe元素
    list.add(1,"AA");
    System.out.println (list);
    System.out.println ("***********");
//    boolean addAll(int index, Collection eLes):从index位置开始将eLes中的所有元素添加进来object get(int index):获取指定index位置的元素
    java.util.List<String> asList = Arrays.asList ("YY", "XX");
    list.addAll (asList);
    System.out.println (list);
    System.out.println ("***********");
//    int indexOf(object obj):返回obj在集合中首次出现的位置
    int i = list.indexOf (456);
    System.out.println (i);
    System.out.println ("***********");
//    int lastIndex0f(Object obj):返回obj在当前集合中末次出现的位置
    int i1 = list.lastIndexOf (456);
    System.out.println (i1);
    System.out.println ("************");
// object remove(int index):移除指定index位置的元素,并返回此元素
    System.out.println (list);
     list.remove ("BB");
    System.out.println (list);
    System.out.println ("****************");
// object set(int index, object ele):设置指定index位置的元素为else
    System.out.println (list);
    list.set (0, "FF");
    System.out.println (list);
    System.out.println ("*****************");
//    list sublist(int fromIndex, int toIndex):返回从fromIndex到toIndex左闭右开位置的子集合
    System.out.println (list);
    java.util.List list1 = list.subList (1,3);
    System.out.println (list1);
    System.out.println ("*****************");

}

6.面试总结:

/*
1.集合Collection中存储的如果是自定义类的对象,需要自定义类重写哪个方法?为什么?
——equals()方法
Set:(HashSet、LinkedHashSet为例): equals()、hashCode()
                   (TreeSet为例): Comparable: compareTo(Object obj)
                                  Comparator: compare(Object o1,Object o2)


2.面试题:ArrayList、 LinkedList、Vector三者的异同?
同:三个类都是实现了List接口,存储数据的特点相同:存储有序的、可重复的数据
不同:见下
collection接口:单列集合,用来存储一个一个的对象
----List接口:存储有序的、可重复的数据。
               “动态数组,替换原有的数组
     ----ArrayList:作为List接口的主要实现类;线程不安全的,效率高;
              底层使用Object[] elementData存储
      ----LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高;
              底层使用双向链表存储
      ----Vector:作为List接口的古老实现类;线程安全的,效率低;
               底层使用Object[] elementData存储

 */

2. Set接口(不常用)

1. set接口的框架:

/*
 set接口的框架:
Collection接口:单列集合,用来存储一个一个的对象
——Set接口:存储无序的、不可重复的据-->高中讲的“集合”
             ----HashSet:作为Set接口的主要实现类;线程不安全的;可以存储null值
      ----LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加的上顺序遍历,时于频繁的遍历操作,LinkedHashSet效率高于HashSet
      ----TreeSet:可以按照添加对象的指定属性,进行排序。

注意: Set接口中没有额外定义新的方法,使用的都是Collection中声明过的方法。
1.Set接口中没有额外定义新的方法,使用的都是Collection中声明过的方法。
2.要求:向Set中添加的数据,其所在的类一定要重写hashcode()和equals()

要求:重写的hashcode()和equals()尽可能保持一致性:相等的对象必须具有相等的散列码


*/

2. set:存储无序的、不可重复的数据


/*
set:存储无序的、不可重复的数据
以HashSet为例说明:
1.无序性:不等于随机性。存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值
2.不可重复性:保证添加的元素按照equals()判断时,不能返回true.即:相同的元素只能添加一个。
*/

3. 添加元素的过程:以HashSet为例:

/*添加元素的过程:以HashSet为例:
我们向HashSet中添加元素a,首先调用元素a所在类的hashcode()方法,计算元素a的哈希值,
此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(即为:索引位置),判断数组此位置上是否已经有元素:
——如果此位置上没有其他元素,则元素α添加成功。--->情况1
——如果此位置上有其他元素b(或以链表形式存在的多个元素),则比较元素a与元素b的hash值:
     ——如果hash值不相同,则元素a添加成功。--->情况2
     ——如果hash 值相同,进而需要调用元素α所在类的equLas()方法:
          ——equals( )返回true,元素α添加失败
          ——equals()返回faLse,则元素a添加成功。--->情况3

对于添加成功的情况2和情况3而言:元素α与已经存在指定索引位置上数据以链表的方式存储。
jdk 7 ∶元素α放到数组中,指向原来的元素。
jdk 8 ∶原来的元素在数组中,指向元素a

总结:七上八下
HashSet底层:数组+链表的结构。
*/

4. LinkedHashSet的使用

/*
LinkedHashSet的使用
LinkedHashSet作为HashSet的子类,在添加数据的同时,每个数据还维护了两个引用,记录此数据的前一个数据和后一个数据。
优点:时于频繁的遍历操作,LinkedHashSet效率高于HashSet
*/

***5. TreeSet的排序

/*
TreeSet的使用
1.向TreeSet中添加的数据,要求是相同类的对象。
2.两种排序方式:  自然排序(实现Comparable接口)  和  定制排序(Comparator)
3.自然排序中,比较两个对象是否相同的标准为: compareTo()返回,不再是equals().
4.定制排序中,比较两个对象是否相同的标准为: compare()返回e.不再是equals().

 */
package production.collection.day01;

import org.junit.Test;

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

public class Set {
//自然排序
@Test
    public  void test(){
    TreeSet treeSet = new TreeSet ();
    treeSet.add(new User ("Mike",15));
    treeSet.add(new User ("Mike",35));
    treeSet.add(new User ("Amy",5));
    treeSet.add(new User ("Jerry",34));
    treeSet.add(new User ("Joy",34));
    treeSet.add(new User ("Bob",4));

    //循环遍历
    Iterator iterator = treeSet.iterator ();
    while(iterator.hasNext ()){
        System.out.println (iterator.next ());
    }
}
    //定制排序
    @Test
    public  void test2(){
        Comparator com =new Comparator () {
            @Override
            public int compare(Object o1, Object o2) {
                if(o1 instanceof User && o2 instanceof  User){
                User u1=(User)o1;
                User u2=(User)o2;
                return  Integer.compare (u1.getAge (),u2.getAge ());

                }else{
                    throw new RuntimeException ("输入的数据类型错误!");
                }
            }
        };
        TreeSet treeSet = new TreeSet (com);
        treeSet.add(new User ("Mike",15));
        treeSet.add(new User ("Mike",35));
        treeSet.add(new User ("Amy",5));
        treeSet.add(new User ("Jerry",34));
        treeSet.add(new User ("Joy",34));
        treeSet.add(new User ("Bob",4));

        //循环遍历
        Iterator iterator = treeSet.iterator ();
        while(iterator.hasNext ()){
            System.out.println (iterator.next ());
        }
    }
}

package production.collection.day01;

import java.util.Objects;

public class User  implements  Comparable{
    private  String name;
    private  int age;

    public User() {
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" + "name='" + name + '\'' + ", age=" + age + '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User)) return false;
        User user = (User) o;
        return getAge () == user.getAge () && Objects.equals (getName (), user.getName ());
    }

    @Override
    public int hashCode() {
        return Objects.hash (getName (), getAge ());
    }

    //重写比较方法
    @Override
    public int compareTo(Object o) {
        if(o instanceof User){
            User  u=(User)o;
            //判断名字是否相等
            int i = this.name.compareTo (u.name);
            if(i!=0){
            return  i;
            }else{
         //如果姓名相同,则对年龄进行从小到大的排序
       //错误写法:System.out.println (this.age.compareTo (u.age));
             return  Integer.compare (this.age,u.age);
            }
        }else{
         throw new RuntimeException ("输入的数据类型错误!");
        }
    }
}

6.课后题

/*
1.定义一个Employee类。
该类包含: private成员变量name,age,birthday,其中 birthday为MyDate 类的对象;,
并为每一个属性定义 getter, setter方法;v并重写 toString方法输出name, age, birthday

MyDate类包含:
private成员变量 year,month,day;
并为每一个属性定义getter,setter方法;

创建该类的5个对象,并把这些对象放入TreeSet集合中(下一章:TreeSet需使用泛型来定义)。
分别按以下两种方式对集合中的元素进行排序,并遍历输出:
1).使Employee实现 Comparable接口,并按name 排序
2).创建 TreeSet时传入Comparator对象,按生日日期的先后排序。
*/
package Test;
/*
MyDate类包含:
private成员变量 year,month,day;
并为每一个属性定义getter,setter方法;
 */
public class MyDate {
    private  int year;


    private  int month;
    private  int day;

    public MyDate() {
    }

    public MyDate(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public int getMonth() {
        return month;
    }

    public void setMonth(int month) {
        this.month = month;
    }

    public int getDay() {
        return day;
    }

    public void setDay(int day) {
        this.day = day;
    }

    @Override
    public String toString() {
        return "MyDate{" + "year=" + year + ", month=" + month + ", day=" + day + '}';
    }
}

package Test;

import java.util.Comparator;

/*
定义一个Employee类。
该类包含: private成员变量name,age,birthday,
其中 birthday为MyDate 类的对象;,
并为每一个属性定义 getter, setter方法;
并重写 toString方法输出name, age, birthday
 */
public class Employee  implements Comparable {
    private  String name;
    private  int age;
    private  MyDate birthday;

    public Employee() {
    }

    public Employee(String name, int age, MyDate birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public MyDate getBirthday() {
        return birthday;
    }

    public void setBirthday(MyDate birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "Employee{" + "name='" + name + '\'' + ", age=" + age + ", birthday=" + birthday + '}';
    }

    @Override
    public int compareTo(Object o) {
     //1).使Employee实现 Comparable接口,并按name 排序
     if(o instanceof  Employee){
         Employee e=(Employee)o;
         return  this.name.compareTo (e.name);
     }else{
        throw new RuntimeException ("输入的数据类型有错误!");
     }

    }
}

package Test;

import org.junit.Test;

import java.util.Comparator;
import java.util.Iterator;

/*
创建该类的5个对象,并把这些对象放入TreeSet集合中
分别按以下两种方式对集合中的元素进行排序,并遍历输出:
1).使Employee实现 Comparable接口,并按name 排序
2).创建 TreeSet时传入Comparator对象,按生日日期的先后排序。
 */
public class TreeSet {
    //1).使Employee实现 Comparable接口,并按name 排序
    @Test
    public void test(){
        java.util.TreeSet set=new java.util.TreeSet ();
        Employee e1=new Employee ("lihua",40,new MyDate (1980,1,1));
        Employee e2=new Employee ("xiaoming",20,new MyDate (2000,12,1));
        Employee e3=new Employee ("lisi",21,new MyDate (1999,4,1));
        Employee e4=new Employee ("zhangsan",40,new MyDate (1980,1,13));
        Employee e5=new Employee ("wangmazi",20,new MyDate (2000,11,1));
        set.add (e1);
        set.add (e2);
        set.add (e3);
        set.add (e4);
        set.add (e5);

        Iterator iterator = set.iterator ();
        while(iterator.hasNext ()){
            System.out.println (iterator.next ());
        }

    }
//2).创建 TreeSet时传入Comparator对象,按生日日期的先后排序。
    @Test
    public void test2(){
        java.util.TreeSet set=new java.util.TreeSet (new Comparator () {
            @Override
            public int compare(Object o1, Object o2) {
                if (o1 instanceof Employee && o2 instanceof Employee) {
                    Employee e1 = (Employee) o1;
                    Employee e2 = (Employee) o2;
                    //写法一、
                    if (e1.getBirthday ().getYear () != e2.getBirthday ().getYear ()) {
                        return Integer.compare (e1.getBirthday ().getYear (), e2.getBirthday ().getYear ());
                    } else if (e1.getBirthday ().getMonth () != e1.getBirthday ().getMonth ()) {
                        return Integer.compare (e1.getBirthday ().getMonth (), e2.getBirthday ().getMonth ());
                    } else if (e1.getBirthday ().getDay () != e2.getBirthday ().getDay ()) {
                        return Integer.compare (e1.getBirthday ().getDay (), e2.getBirthday ().getDay ());
                    }
//

                    //写法二:
//                    MyDate myDate1 = e1.getBirthday ();
//                    MyDate myDate2 = e2.getBirthday ();
//                    int year = myDate1.getYear () - myDate2.getYear ();
//                    int month = myDate1.getMonth () - myDate2.getMonth ();
//                    int day = myDate1.getDay () - myDate2.getDay ();
//                    if(year!=0){
//                        return  year;
//                    }else if(month!=0){
//                        return  month;
//                    }else if(day!=0){
//                        return  day;
//                    }

                }
                    return 0;

            }
        });

        Employee e1=new Employee ("lihua",40,new MyDate (1980,1,1));
        Employee e2=new Employee ("xiaoming",20,new MyDate (2000,12,1));
        Employee e3=new Employee ("lisi",21,new MyDate (1999,4,1));
        Employee e4=new Employee ("zhangsan",40,new MyDate (1980,1,13));
        Employee e5=new Employee ("wangmazi",20,new MyDate (2000,11,1));
        set.add (e1);
        set.add (e2);
        set.add (e3);
        set.add (e4);
        set.add (e5);

        Iterator iterator = set.iterator ();
        while(iterator.hasNext ()){
            System.out.println (iterator.next ());
        }

    }
}

6、Map接口

1.Map实现类的结构

/*
一、Map实现类的结构:
/----Map:双列数据,存储key-value对的数据---类似于高中的函数: y =f(x)
/----HashMap:作为Nap的主要实现类;线程不安全的,效率高;存储nuLl的key和vaLue
        /----LinkedHashMap:保证在遍历map元素时,可以按照添加的顺序实现遍历。
                       原因:在原有的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。
                       对于频繁的遍历操作,此类执行效率高于HashMap 。
/----TreeMap:保证按照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序
              底层使用红黑树
/----Hashtable:作为古老的实现类;线程安全的,效率低;不能存储null的key和value
        / ----Properties:常用来处理配置文件。key和value都是String类型


HashMap的底层:数组+链表(jdk7及之前)
              数组+链表+红黑树(jdk 8)
*/

2.Map结构的理解

/*
二、Map结构的理解:
Map中的key:无序的、不可重复的,使用Set存储所有的key————> key所在的类要重写equals()和hashcode() (以HashMap为例)
Map中的value:无序的、可重复的,使用collection存储---——>value所在的类要重写equals()
     所有的value一个键值对: key-value构成了一个entry对象。
Map中的entry:无序的、不可重复的,使用Set存储所有的entry

*/

***3.HashMap的底层实现原理:jdk7为例

/*
三、HashMap的底层实现原理?jdk7为例说明:
HashMap map = new HashMap():  //在实例化以后,底层创建了长度是16的一维数组Entry[]table.
...可能已经执行过多次put. . .
map.put(key1, value1);
首先,调用key1所在类的nashCode()计算xey1哈希值,此哈希值经过某种算法计算以后,得到在Entry数组中的存放位置。
如果此位置上的数据为空,此时的key1-value1添加成功。----情况1
如果此位置上的数据不为空,(意味着此位置上存在一个或多个数据(以键表形式存在)),比较key1和已经存在的一个或多个数据的哈希值:
        如果key1的哈希值与已经存在的数据的哈希值都不相同,此时key1-value1添加成功。----情况2
        如果key1的哈希值和已经存在的某一个数据( key2-vaLue2)的哈希值相同,继续比较:调用key1所在类的equals(key2)
                  如果equals()返回faLse:此时key1-vaLue1添加成功。----情况3
                  如果equals()返回true:使用value1替换vaLue2 。

补充:关于情况2和情况3:此时key1-value1和原来的数据以链表的方式存储。

扩容:在不断的添加过程中,会涉及到扩容问题,当超出临界值(且要存放的位置非空)时,扩容。
默认的扩容方式:扩容为原来容量的2倍,并将原有的数据复制过来。

*/

***4.HashMap的底层实现原理中jdk8对比jdk7

/*
四、HashMap的底层实现原理中jdk8相较于jdk7在底层实现方面的不同:
1. new HashMap():底层没有创建一个长度为16的数组2. jdk8底层的数组是:Node[],而非Entry[]
3.首次调用put()方法时,底层创建长度为16的数组
4. jdk7底层结构只有:数组+链表。jdk8中底层结构:数组+链表+红黑树。
     当数组的某一个索引位置上的元素以链表形式存在的数据个数>8且当前数组的长度>64时,
     此时此索引位置上的所有数据改为使用红黑树存储。I

DEFAULT_INITIAL_ CAPACITY : HashMap的默认容量,16
DEFAULT_LOAD_FACTOR: HashMap的默认加载因子:0.75
threshold:扩容的临界值,=容量*填充因子:16 * 0.75 =>12
TREEIFY_ THRESHOLD: Bucket中链表长度大于该默认值,转化为红黑树:8
MIN_ TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量:64

*/

5.LinkedHashMap的底层实现原理(了解)

/*
五、LinkedHashMap的底层实现原理(了解)
源码中:
static class Entry<K,V>extends HashMap.Node<K,V> {
      Entry<K,V> before,after;//能够记录添加的元素的先后顺序
      Entry (int hash,K key, v value,Node<K,V> next) {
         super( hash,key, value, next);
     }
}
*/

6.Map中定义的方法

1.添加、删除、修改操作:

/*
添加、删除、修改操作:
Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
void putALL(Map m):将m中的所有key-value对存放到当前map 中
Object remove(Object key):移除指定key 的key-value对,并返回value
void clear :清空当前map 中的所有数据
*/
    @Test
    public  void test1(){
//    添加、删除、修改操作:
        HashMap map=new HashMap ();
//    Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
        //添加
        map.put ("AA",123);
        map.put ("BB",456);
        map.put ("CC",789);
        //修改
        map.put ("BB",999);
        System.out.println (map);
//    Object remove(Object key):移除指定key 的key-value对,并返回value
        Object aa = map.remove ("AA");
        System.out.println (aa);
        System.out.println (map);
//    void putALL(Map m):将m中的所有key-value对存放到当前map 中
        HashMap map1=new HashMap ();
        map1.put ("DD",789);
        map.putAll (map1);
        System.out.println (map);
//    void clear :清空当前map 中的所有数据
        map.clear ();
        System.out.println (map);
    }

2.元素查询的操作:

/*
元素查询的操作:
object get(Object key):获取指定key对应的value
booLean containsKey(object key):是否包含指定的key
boolean containsValue(Object value):是否包含指定的value
int size():返回map 中key-value对的个数
booLean isEmpty():判断当前map是否为空
boolean equals(Object obj):判断当前map和参数对象obj是否相等
*/
    @Test
    public  void test2(){
//        元素查询的操作:
        HashMap map=new HashMap ();
        map.put ("AA",123);
        map.put ("BB",456);
        map.put ("CC",789);
//        object get(Object key):获取指定key对应的value
        Object aa = map.get ("AA");
        System.out.println (aa);
//        booLean containsKey(object key):是否包含指定的key
        boolean bb = map.containsKey ("BB");
        System.out.println (bb);
//        boolean containsValue(Object value):是否包含指定的value
        boolean b = map.containsValue (123);
        System.out.println (b);
//        int size():返回map 中key-value对的个数
        int size = map.size ();
        System.out.println (size);
//        booLean isEmpty():判断当前map是否为空
        boolean empty = map.isEmpty ();
        System.out.println (empty);
//        boolean equals(Object obj):判断当前map和参数对象obj是否相等

    }

3.元视图操作的方法:

/*
元视图操作的方法:
set keySet():返回所有key构成的set集合
collection values():返回所有vaLue构成的Collection集合
set entrySet():返回所有key-vaLue对构成的Set集合

 */

    @Test
    public  void test3(){
//        元视图操作的方法:
        HashMap map=new HashMap ();
        map.put ("AA",123);
        map.put ("BB",456);
        map.put ("CC",789);
//        set keySet():返回所有key构成的set集合
        Set set = map.keySet ();
        Iterator iterator = set.iterator ();
        while(iterator.hasNext ()){
            System.out.println (iterator.next ());
        }
        System.out.println ("************");
//        collection values():返回所有vaLue构成的Collection集合
        Collection collection = map.values ();
        for (Object o:collection
             ) {
            System.out.println (o);
        }
        System.out.println ("***************");
//        set entrySet():返回所有key-vaLue对构成的Set集合
        Set entrySet = map.entrySet ();
        Iterator iterator1 = entrySet.iterator ();
        while (iterator1.hasNext ()){
            Object o = iterator1.next ();
            //entrySet集合中的所有元素都是entry类型
            java.util.Map.Entry entry=(java.util.Map.Entry)o;
            System.out.println (entry.getKey ()+"="+entry.getValue ());
        }
    }

4.总结:常用方法+面试题

/*
总结:常用方法:
添加: put (Object key , object value)
删除:remove(Object key)
修改:put (Object key , object value)
查询: get(object key)
长度: size()
遍历:keySet() / values() / entrySet(
*/

/*
面试题:
1. HashMap的底层实现原理?
2. HashMap和Hashtable的异同?
3. CurrentHashMap与Hashtable的异同?(暂时不讲)
 */

7.TreeMap两种添加方式的使用

//TreeMap两种添加方式的使用
//向TreeMap中添加key-value,要求key必须是由同一个类创建的对象
// 因为要按照key进行排序:自然排序、定制排序
    
//自然排序
 @Test
 public  void test1() {
     TreeMap map = new TreeMap ();
     User u1 = new User ("Amy", 11);
     User u2 = new User ("Jerry", 15);
     User u3 = new User ("Tom", 13);
     map.put (u1, 99);
     map.put (u2, 69);
     map.put (u3, 89);
     // set entrySet():返回所有key-vaLue对构成的Set集合
     Set entrySet = map.entrySet ();
     Iterator iterator1 = entrySet.iterator ();
     while (iterator1.hasNext ()) {
         Object o = iterator1.next ();
         //entrySet集合中的所有元素都是entry类型
         java.util.Map.Entry entry = (java.util.Map.Entry) o;
         System.out.println (entry.getKey () + "=" + entry.getValue ());

     }
 }
 //定制排序
 @Test
 public  void test2() {
     TreeMap map = new TreeMap (new Comparator () {
         @Override
         public int compare(Object o1, Object o2) {
             if(o1 instanceof  User && o2 instanceof  User){
                 User u1=(User)o1;
                 User u2=(User)o2;
                 return  Integer.compare (u1.getAge (),u2.getAge ());
             }else{
                 throw  new RuntimeException ("输入的数据类型错误!");
             }
         }
     });
     User u1 = new User ("Amy", 11);
     User u2 = new User ("Jerry", 15);
     User u3 = new User ("Tom", 13);
     map.put (u1, 99);
     map.put (u2, 69);
     map.put (u3, 89);
     // set entrySet():返回所有key-vaLue对构成的Set集合
     Set entrySet = map.entrySet ();
     Iterator iterator1 = entrySet.iterator ();
     while (iterator1.hasNext ()) {
         Object o = iterator1.next ();
         //entrySet集合中的所有元素都是entry类型
         java.util.Map.Entry entry = (java.util.Map.Entry) o;
         System.out.println (entry.getKey () + "=" + entry.getValue ());

     }
 }
package production.collection.day01;

import java.util.Objects;

public class User  implements  Comparable{
    private  String name;
    private  int age;

    public User() {
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" + "name='" + name + '\'' + ", age=" + age + '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User)) return false;
        User user = (User) o;
        return getAge () == user.getAge () && Objects.equals (getName (), user.getName ());
    }

    @Override
    public int hashCode() {
        return Objects.hash (getName (), getAge ());
    }

    //重写比较方法
    @Override
    public int compareTo(Object o) {
        if(o instanceof User){
            User  u=(User)o;
            //判断名字是否相等
            int i = this.name.compareTo (u.name);
            if(i!=0){
            return  i;
            }else{
         //如果姓名相同,则对年龄进行从小到大的排序
       //错误写法:System.out.println (this.age.compareTo (u.age));
             return  Integer.compare (this.age,u.age);
            }
        }else{
         throw new RuntimeException ("输入的数据类型错误!");
        }
    }
}

8.Properties处理属性文件

详细看JDBC总结

7、Collections工具类的使用

1.常用方法:

/*
collections:  操作Collection、Map的工具类

面试题:Collection和collections的区别?

常用方法:
——reverse(List):反转List中元素的顺序
shuffle(List):对 List集合元素进行随机排序
sort(List):根据元素的自然顺序对指定List集合元素按升序排序
sort(List,Comparator):根据指定的Comparator产生的顺序对List 集合元素进行排序
swap(List, int,int):将指定list集合中的i处元素和j处元素进行交换
object max(collection):根据元素的自然顺序,返回给定集合中的最大元素
object max(collection,Comparator):根据Comparator指定的顺序,返回给定集合中的最大object min(collection)
object min(collection,comparator)
int frequency(Collection,object):返回指定集合中指定元素的出现次数
——void copy(List dest,List src):将src中的内容复制到dest中
boolean replaceAll(List list,object oldVal,object newVal):使用新值替换List对象里的值
——collections类中提供了多个synchronizedXxx()方法,该方法可使将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题
*/
@Test
    public  void test(){
   // void copy(List dest,List src):将src中的内容复制到dest中
    List list = new ArrayList ();
    list.add (123);
    list.add(11);
    list.add (99);
//错误写法:IndexOutOfBoundsException: Source does not fit in dest
//   List dest =new ArrayList ();
//    Collections.copy (dest,list);
//正确写法:
    List<Object> dest = Arrays.asList (new Object[list.size ()]);
    Collections.copy (dest,list);
    System.out.println (dest);
}


@Test
    public void test2(){
//    collections类中提供了多个synchronizedXxx()方法,该方法可使将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题
    List list = new ArrayList ();
    list.add (123);
    list.add(11);
    list.add (99);
    List list1 = Collections.synchronizedList (list);
    System.out.println (list1);//此时的list1是线程安全的
    }

2.练习题:

//1.请从键盘随机输入10个整数保存到List中,并按倒序、从大到小的顺序显示出来
    
//⒉请把学生名与考试分数录入到集合中,并按分数显示前三名成绩学员的名字。

/*3、姓氏统计:一个文本文件中存储着北京所有高校在校生的姓名,格式每行一个名字,姓与名以空格分隔:
张  三
李  四
王  小五
现在想统计所有的姓氏在文件中出现的次数,请描述一下你的解决方案。
*/

练习1:


//1.请从键盘随机输入10个整数保存到List中,并按倒序、从大到小的顺序显示出来
@org.junit.Test
    public  void test1(){
   ArrayList<Object> list = new ArrayList<> ();
   for(int i=0;i<10;i++){
       //获取a到b之间的随机数
       //(int) (Math.random ()*(b-a+1)+a)
       //获取一个[0,100]的随机数
    int random = (int) (Math.random ()*(100)+1);
    list.add(random);
   }
    System.out.println (list);
    System.out.println ("*******************");
    //Collections工具类中reverse(List):反转List中元素的顺序
    Collections.reverse (list);
    System.out.println (list);
    System.out.println ("*******************");
    //从大到小的顺序显示出来
    //Collections工具类中sort(List,Comparator):根据指定的Comparator产生的顺序对List 集合元素进行排序
    Collections.sort (list, new Comparator<Object> () {

        @Override
        public int compare(Object o1, Object o2) {
            if(o1 instanceof  Object && o2 instanceof Object){
                Object x=(Object)o1;
                Object y=(Object)o2;
                Integer  i=(Integer)x;
                Integer  j=(Integer)y;
                return  Integer.compare (i,j);
            }
            throw new RuntimeException ("数据类型有错误");
        }
    });
    System.out.println (list);
}

练习2:

//⒉请把学生名与考试分数录入到集合中,并按分数显示前三名成绩学员的名字。
//方法一:
    @org.junit.Test
    public  void test2(){
    //注意这里,HashSet无序,不可排序。TreeSet可以自定义排序
      Set set=new TreeSet ();
//        List set=new LinkedList ();
        Students s1=new Students ("zhangsan",60);
        Students s2=new Students ("lisi",70);
        Students s3=new Students ("wangmazi",30);
        Students s4=new Students ("xiaoming",35);
        Students s5=new Students ("xiaohong",80);
        set.add (s1);
        set.add (s2);
        set.add (s3);
        set.add (s4);
        set.add (s5);
//      System.out.println (set);
        Iterator iterator = set.iterator ();
        while(iterator.hasNext ()){
            System.out.println (iterator.next ());
        }
        System.out.println ("*******************");
        Iterator iterator2 = set.iterator ();
        for (int i = 0; i <3 ; i++) {
            System.out.println (iterator2.next ());
        }

    }
//方法二:
    @org.junit.Test
    public  void test22(){
        //注意这里,HashSet无序,不可排序。TreeSet可以自定义排序
      List list=new LinkedList ();
        Students s1=new Students ("zhangsan",60);
        Students s2=new Students ("lisi",70);
        Students s3=new Students ("wangmazi",30);
        Students s4=new Students ("xiaoming",35);
        Students s5=new Students ("xiaohong",80);
        list.add (s1);
        list.add (s2);
        list.add (s3);
        list.add (s4);
        list.add (s5);
        Collections.sort (list);
       System.out.println (list);
       System.out.println ("*******************");
//若用list sublist(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合
        List list1 = list.subList (0,3);
        System.out.println (list1);
    }
package day01;

public class Students implements Comparable{
    private  String name;
    private  int  grade;

    public Students() {
    }

    public Students(String name, int grade) {
        this.name = name;
        this.grade = grade;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getGrade() {
        return grade;
    }

    public void setGrade(int grade) {
        this.grade = grade;
    }

    @Override
    public String toString() {
        return "Students{" + "name='" + name + '\'' + ", grade=" + grade + '}';
    }


    @Override
    public int compareTo(Object o) {
        if(o instanceof  Students){
            Students s=(Students)o;
       return Integer.compare (this.grade,s.grade);

        }
        throw new RuntimeException ("数据类型有错误");
    }
}

练习3:

/*3、姓氏统计:一个文本文件中存储着北京所有高校在校生的姓名,格式每行一个名字,姓与名以空格分隔:
张  三
李  四
王  小五
现在想统计所有的姓氏在文件中出现的次数,请描述一下你的解决方案。
*/
https://blog.csdn.net/qq_52360788/article/details/118771494
举报

相关推荐

0 条评论