Java集合

集合的理解和好处

  • 首先我们前面的学习中保存多个数据用的是数组,那么数组有什么不足的地方呢。

  • 数组:

    1. 长度开始时必须指定,而且一旦指定,不能更改。
    2. 保存的必须为同一类型元素。
    3. 使用数组进行增加/删除元素的示意代码--比较麻烦
  • 写出Person数组扩容的示意图

Person[] pers = new Person[1];
pers[0] = new Person;
  • 怎样增加新的Person对象
Person[] person2 = new Person[person.length+1];//创建一个新的数组,长度比之前的长
for (int i=0;i<=person.length;i++){//拷贝person数组的元素大到到person2
    person2[i] = person[i];
	}
person2[person2.length-1] =new Person();//添加新的对象
}
  • 集合:

    1. 可以动态的保存任意多个对象,使用起来比较方便。
    2. 提供了一系列方便的操作对象的方法:add(添加),remove(删除),set(修改),get(获得)等。
    3. 使用了集合添加,删除新元素的示意代码更加简洁名了。

集合框架体系

  • Java的集合类有很多,主要分为两大类(单列集合,双列集合)如图要背下来

  • Collection(单列集合):存放的是单个单个的元素。
  • Map(双列集合):存放的是键值对(Key-Value)形式。

collection

  • Collection接口实现类的特点

    public interface Collection extends Iterable

    1. Collection实现子类可以存放多个元素,每个元素可以是Object。

    2. 有些Collection的实现类,可以存放重复的元素,有些不可以。

    3. 有些Collection的实现类,有些是有序的(List),有些不是有序的(Set)。

      有序:存放的顺序和取出的顺序保持一致。

    4. Collection接口没有直接的实现子类,是通过它的子接口Set和List来实现的。

  • 介绍Collection接口常用的方法,这里使用它的子类ArrayList来演示:

    1. add();添加单个元素。
    2. remove();删除指定元素。
    3. contains();查找元素是否存在。
    4. size();获取元素个数。
    5. isEmpty();判断是否为空。
    6. clear();清空。
    7. addAll();添加多个元素。
    8. containsAll();查找多个元素是否都存在。
    9. removeAll();删除多个元素。
public class CollectionWaysTest {
    public static void main(String[] args) {
        new CollectionWaysTest().m1();
    }
    public void m1(){
        ArrayList<Object> list = new ArrayList<>();
        //1. add();添加单个元素。
        list.add("tom");//添加字符串
        list.add(100);//添加整型,这里会自动装箱add(new Integer(100));
        list.add(true);//添加布尔型,这里会自动装箱
        System.out.println(list);//结果:[tom, 100, true]


        //2. remove();删除指定元素。
            //第一种方式:list.remove(Object obj);
            list.remove("tom");//按照对象名删除指定元素.
            //第二种方式:list.remove(int num);
            list.remove(0);//按照数组下标删除指定元素.
            System.out.println(list);//结果:[true]


        //3. contains(Object obj);查找元素是否存在。
        System.out.println(list.contains("100"));//结果:false


        //4. size();获取元素个数(长度)。
        System.out.println(list.size());//结果:1


        //5. isEmpty();判断是否为空。
        System.out.println(list.isEmpty());//结果:false


        //6. clear();清空元素。
        list.clear();


        //7. addAll(Collection col);添加多个元素。可以传入任何只要是实现了Collection接口的子类对象。
        ArrayList<Object> newList = new ArrayList<>();
        newList.add("newTom");
        newList.add("new100");
        newList.add("newTrue");
        list.addAll(newList);
        System.out.println(list);//结果:[newTom, new100, newTrue]


        //8. containsAll();查找多个元素是否都存在。可以传入任何只要是实现了Collection接口的子类对象。
        System.out.println(list.containsAll(newList));//结果:true


        //9. removeAll();删除多个元素。可以传入任何只要是实现了Collection接口的子类对象。
        list.removeAll(newList);
        System.out.println(list);//结果:[]
    }
}

Collection接口遍历元素

Collection接口遍历元素方式1(使用Iterator(迭代器))

  1. Iterator对象称为迭代器,主要用于遍历Collection集合中的元素。
  2. 实现Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象,既可以返回一个迭代器。
  3. Iterator仅用于遍历集合,Iterator本身不存放对象。

案例演示:

public class IteratorTest {
    public static void main(String[] args) {
        IteratorTest iteratorTest = new IteratorTest();
        iteratorTest.m1();
    }
   public void m1(){
        //1.初始化一个集合list
       Collection col = new ArrayList();//父类引用指向子类对象,实现向上转型。方便下面创建迭代器
       col.add(new Book("三国演义","罗贯中",10.4));
       col.add(new Book("红楼梦","曹雪芹",20.3));
       col.add(new Book("小李飞刀","古龙",14.9));
       
       //2.使用迭代器遍历集合
       Iterator iterator = col.iterator();//创建迭代器
       //快速生成while循环快捷键:itit              显示所有快捷键的快捷键ctrl+j
       while (iterator.hasNext()){//hasNext()判断下一个元素是否存在,是则返回true,否则返回false
           System.out.println(iterator.next());//iterator.next()1.向下移动一次2.将当前元素的值返回,类型是Object。
           /*结果:Book{name='三国演义', auther='罗贯中', price=10.4}
                  Book{name='红楼梦', auther='曹雪芹', price=20.3}
                  Book{name='小李飞刀', auther='古龙', price=14.9}
           */
       }
       //3.当退出while循环后,迭代器Iterator指向最后一个元素,如果下面再去使用另一个Iterator去遍历,就会报错:NoSuchElementException。
       //4.如果希望再次遍历,需要重置我们的迭代器。
       iterator = col.iterator();//重新创建一次即可
   }
}
class Book{
    private String name;
    private String auther;
    private double price;
    public Book() {
    }
    public Book(String name, String auther, double price) {
        this.name = name;
        this.auther = auther;
        this.price = price;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAuther() {
        return auther;
    }
    public void setAuther(String auther) {
        this.auther = auther;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", auther='" + auther + '\'' +
                ", price=" + price +
                '}';
    }
}

总结要点:

  1. 父类引用指向子类对象,实现向上转型。方便下面创建迭代器。
  2. 快速生成while循环快捷键:itit,显示所有快捷键的快捷键ctrl+j。
  3. iterator.hasNext()判断下一个元素是否存在,是则返回true,否则返回false。
  4. iterator.next()1.向下移动一次2.将当前元素的值返回,类型是Object。
  5. 当退出while循环后,迭代器Iterator指向最后一个元素,如果下面再去使用另一个Iterator去遍历,就会报错:NoSuchElementException。
  6. 如果希望再次遍历,需要重置我们的迭代器。iterator = col.iterator();//重新创建一次即可

Collection接口遍历元素方式2(for循环增强)

  • 增强型for循环,可以替代iterator迭代器,特点:增强for循环就是简化版的iterator,本质一样。只能用于遍历集合或者数组。
  • 基本语法:
for (元素类型 元素名:集合名或数组名) {
    访问元素
}
  • 案例演示:
public class IteratorTest {
    public static void main(String[] args) {
        IteratorTest iteratorTest = new IteratorTest();
        iteratorTest.m2();
    }
    //使用for-each遍历集合
    public void m2(){
        //1.初始化一个集合list
        Collection col = new ArrayList();//父类引用指向子类对象,实现向上转型。方便下面创建迭代器,也可以用list的引用
        col.add(new Book("三国演义","罗贯中",10.4));
        col.add(new Book("红楼梦","曹雪芹",20.3));
        col.add(new Book("小李飞刀","古龙",14.9));
        System.out.println(col);//结果:[Book{name='三国演义', auther='罗贯中', price=10.4}, Book{name='红楼梦', auther='曹雪芹', price=20.3}, Book{name='小李飞刀', auther='古龙', price=14.9}]
        //2.使用for-each遍历集合
        for (Object obj:col) {
            System.out.println(obj);
          /*结果:Book{name='三国演义', auther='罗贯中', price=10.4}
                  Book{name='红楼梦', auther='曹雪芹', price=20.3}
                  Book{name='小李飞刀', auther='古龙', price=14.9}
           */
        }
    }
}
class Book{
    private String name;
    private String auther;
    private double price;
    public Book() {
    }
    public Book(String name, String auther, double price) {
        this.name = name;
        this.auther = auther;
        this.price = price;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAuther() {
        return auther;
    }
    public void setAuther(String auther) {
        this.auther = auther;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", auther='" + auther + '\'' +
                ", price=" + price +
                '}';
    }

List

  • ArrayList、LinkedList的比较和如何选择:

  • List接口基本介绍:

    List接口是Collection接口的子接口。常用实现类有:ArrayList、LinkedList、Vector。

    1. List集合类中元素有序(即添加顺序和取出顺序一致),且元素可重复。
    2. List集合中的每个元素都有其对应的顺序索引,即支持索引。
    3. List容器中的元素都对应一个整数型的序号记载在容器中的位置,可以根据序号存取容器中的元素。
public class ListTest {
    public static void main(String[] args) {
        List list = new ArrayList();
        //1. List集合类中元素有序(即添加顺序和取出顺序一致),且元素可重复。
        list.add("tom");
        list.add("jack");
        list.add("mary");
        list.add("tom");
        list.add("mary");
        System.out.println("List="+list);//结果:List=[tom, jack, mary, tom, mary]
        //2. List集合中的每个元素都有其对应的顺序索引,即支持索引。
        System.out.println(list.get(1));//结果:jack
    }
}
  • List接口的常用方法:

    1. void add(int index,Object ele);在index处插入ele元素。
    2. boolean addAll(int index,Collection eles);从index位置开始将eles中的所有元素添加进来。
    3. Object get(int index);获取指定index位置的元素。
    4. int indexOf(Object obj);返回obj在集合中首次出现的位置。
    5. int lastIndexOf(Object obj);返回obj在集合中最后出现的位置。
    6. Object remove(int index);移除指定index位置的元素,并返回此元素。
    7. Object set(int index,Object ele);替换指定index位置的元素为ele,被替换的元素必须存在。
    8. List subList(int fromIndex,int toIndex);返回从fromIndex到toIndex位置(不包含toIndex位置)的子集合。
public class ListTest {
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("wsn");
        list.add(100);
        list.add(true);
        list.add("wsn");
        list.add(100);
        list.add("jack");
        //1. void add(int index,Object ele);在index处插入ele元素。
        list.add(1,"newAdd");//在集合list第2个位置添加一个新的元素"newAdd"。
        System.out.println(list);//结果:[wsn, newAdd, 100, true]

        //2. boolean addAll(int index,Collection eles);从index位置开始将eles中的所有元素添加进来。
        List newList = new ArrayList();
        newList.add("newList01");
        newList.add("newList02");
        newList.add("newList03");
        list.addAll(2,newList);//在集合list第3个位置将集合newList的元素全部添加。
        System.out.println(list);//结果:[wsn, newAdd, newList01, newList02, newList03, 100, true]

        //3. Object get(int index);获取指定index位置的元素。
        System.out.println(list.get(4));//获取list集合第5个位置的元素。结果:newList03

        //4. int indexOf(Object obj);返回obj在集合中首次出现的位置。
        System.out.println(list.indexOf(100));//获取list集合100元素首次出现的位置。结果:5

        //5. int lastIndexOf(Object obj);返回obj在集合中最后出现的位置。
        System.out.println(list.lastIndexOf("wsn"));//获取list集合"wsn"元素最后出现的位置。结果:7

        //6. Object remove(int index);移除指定index位置的元素,并返回此元素。
        list.remove(6);//移除集合list第7个位置的元素,也可以直接传入元素名进行移除
        System.out.println(list);//结果:[wsn, newAdd, newList01, newList02, newList03, 100, wsn, 100, jack]

        //7. Object set(int index,Object ele);修改指定index位置的元素为ele,相当于是替换。
        list.set(3,"update");//修改集合list第4个位置元素为“update”
        System.out.println(list);//[wsn, newAdd, newList01, update, newList03, 100, wsn, 100, jack]

        //8. List subList(int fromIndex,int toIndex);返回从fromIndex到toIndex位置(不包含toIndex位置)的子集合。
        System.out.println(list.subList(5, 8));//返回集合list从5到8位置(不包含8位置)的子集合.结果:[100, wsn, 100]
    }
}

集合排序练习:

 /*
    * 使用List的实现类添加三本书,并遍历,打印效果如下
    * 名称:xx      价格:xx        作者:xx
    * 名称:xx      价格:xx        作者:xx
    * 名称:xx      价格:xx        作者:xx
    * 要求:1.按价格排序,从低到高(使用冒泡法)。
    *      2.要求使用ArrayList,LinkedList,Vector三种集合实现。
    *      3.结论:主要说明,只要实现了List接口,那么List的实现类都可以使用List接口中的方法。
    * */
public class ListExercise {
    public static void main(String[] args) {
        new ListExercise().m2();
    }
    @SuppressWarnings({"all"})
    public void m2(){
        List list = new ArrayList();
        Scanner sc = new Scanner(System.in);
        //循环输入书本信息
        for (int i = 0; i < 3; i++) {
            System.out.println("请输入第"+(i+1)+"本书的名称,价格,作者");
            Booknew booknew = new Booknew(sc.next(), sc.nextDouble(), sc.next());
            list.add(booknew);
        }
        //for-each遍历(未排序之前)
        System.out.println("============= 未排序之前 ==============");
        for (Object obj:list) {
            System.out.println(obj);
        }
        ListExercise listExercise = new ListExercise();
        listExercise.sort(list);//调用排序方法
        System.out.println("============= 排序之后 ==============");
        //for-each遍历(排序之后)
        for (Object obj:list) {
            System.out.println(obj);
        }
        sc.close();//关闭流
    }
    //集合排序方法
    public void sort(List list){//将list集合传入
        int listSize = list.size();//将list.size()提出,提高循环效率。
        //冒泡排序
        for (int i = 0; i < listSize-1; i++) {
            for (int j = 0; j <listSize-1-i ; j++) {
                Booknew b1 = (Booknew)list.get(j);//获取list的当前元素并向下转型,就可以获取到价格price去比较
                Booknew b2 = (Booknew)list.get(j+1);//获取list的当前元素并向下转型,就可以获取到价格price去比较
                if (b1.getPrice()> b2.getPrice()){//比较大小
                    //如果true,就用list.set(int index,Object ele)交换,
                    list.set(j,b2);
                    list.set(j+1,b1);
                }
            }
        }
    }
}
class Booknew{
    private String name;
    private double price;
    private String auther;
    public Booknew(String name, double price, String auther) {
        this.name = name;
        this.price = price;
        this.auther = auther;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    public String getAuther() {
        return auther;
    }
    public void setAuther(String auther) {
        this.auther = auther;
    }
    @Override
    public String toString() {
        return "名称:" + name +"\t\t\t"+ "价格:" + price+"\t\t\t"+ "作者:" + auther;
    }
}

ArrayList

  • 注意事项:

    1. ArrayList可以添加任意元素(元素可以重复),包括null。
    2. ArrayList是由数组来实现数据的存储的。
    3. ArrayList基本等同于Vector,除了ArrayList是线程不安全的(执行效率高),在多线程的情况下,不建议用ArrayList。

  • ArrayList底层结构和源码分析:

    1. ArrayList中维护了一个Object类型的数组elementDate。

      transient Object[] elementData;//transient 表示瞬间,短暂。表示该属性不会被序列化。
      
    2. 当创建ArrayList对象时,如果使用的是无参构造,则初始的elementData容量为0,第一次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。

    3. 如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要再次扩容,则直接扩容elementData为1.5倍。

LinkedList

  • 基本介绍:

    1. LinkedList实现了双向链表和双端队列的特点。
    2. 可以添加任意元素(元素可以重复),包括null。
    3. 线程不安全,没有实现同步。
  • LinkedList底层操作机制:

    1. LinkedList底层维护了一个双向链表。
    2. LinkedList中维护了两个属性,first和last分别指向首节点和尾节点。
    3. 每个节点(Node对象),里面又维护了prev,next,item三个属性,其中通过prev指向前一个,通过next指向后一个介蒂安,实现双向链表。
    4. 所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高。

Vector

  • Vector基本介绍:

    1. Vector类的定义说明.

    2. Vector底层也是一个数组对象,protected Object[] elementData;

    3. 在开发中,需要线程同步安全时,考虑使用Vector。

    4. Vector是线程同步的,即线程安全,Vector类的操作方法带有synchronized

     //Vector类get()方法源码
    public synchronized E get(int index) {
         if (index >= elementCount)
             throw new ArrayIndexOutOfBoundsException(index);
    
         return elementData(index);
    }
    

Set

  • Set接口基本介绍:

    1. 无序(添加和取出的顺序不一致),没有索引。
    2. 不允许重复元素,所以最多包含一个null。
  • Set接口的常用方法:

    和List接口一样,Set接口也是Collection的子接口,因此,常用的方法和List一样。

  • Set接口的遍历方式:

    1. 可以使用迭代器。
    2. 增强for循环。
    3. 不能使用索引(也就普通for循环)的方式获取。
public class HashSetTest {
    public static void main(String[] args) {
        new HashSetTest().m1();
    }
    /*
    * HashSet遍历
    * 1.重复的元素不会存入,顺序也是无序的。
    * 2.虽然是无序的,但位置是固定的。
    * */
    @SuppressWarnings({"all"})
    public void m1(){
        Set hashSet = new HashSet();
        hashSet.add("jhon");
        hashSet.add("jack");
        hashSet.add("mary");
        hashSet.add("jhon");
        hashSet.add("null");
        hashSet.add("null");
        //重复的元素不会存入,顺序也是无序的
        System.out.println(hashSet);//结果:[null, mary, jhon, jack]
        //增强遍历
        for (Object obj:hashSet) {
            System.out.println(obj);
        }
        //迭代器遍历
        Iterator iterator = hashSet.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}

HashSet

  • HashSet介绍:

    1. HashSet实现了Set接口。
    2. 可以存放null值,但只能是一个。
    3. 不能有重复的元素,在前面Set讲过。
    4. Set接口没有get方法。
    5. HashSet实际上是HashMap,源码如下:
Pubilc HashSet(){
	map = new HashMap<>();
}
  • 案例演示:
//1.在执行add方法后,会返回一个boolean值
//2.如果添加成功返回true,否则返回false
System.out.println(hashSet.add("null"));//结果:true
System.out.println(hashSet.add("123"));//结果:true
System.out.println(hashSet.add("345"));//结果:true
System.out.println(hashSet.add("null"));//结果:false
public class HashSetTest {
    public static void main(String[] args) {
        new HashSetTest().m1();
    }
    /*
    * 从1.和2.来看结论似乎是冲突的,为什么Duck两个不一样对象能添加成功,而String两个不一样对象为什么不能添加,这个问题具体要看底层add方法具体是怎么添加的,先知道结论,这个问题以后再说。
    * */
    @SuppressWarnings({"all"})
    public void m1(){
        Set hashSet = new HashSet();
        System.out.println(hashSet.add("jhon"));//结果:true
        System.out.println(hashSet.add("jack"));//结果:true
        System.out.println(hashSet.add("jhon"));//结果:false
        //1.当用Duck类实例化两个新的对象用同的内容添加,结果添加成功
        System.out.println(hashSet.add(new Duck("tom")));//结果:true
        System.out.println(hashSet.add(new Duck("tom")));//结果:true
        //2.当用String类实例化两个对象用同的内容添加,结果不能添加
        System.out.println(hashSet.add(new String("mary")));//结果:true
        System.out.println(hashSet.add(new String("mary")));//结果:false
    }
}
class Duck{
    private String name;
    public Duck(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return  name ;
    }
}
  • 案例演示:
/*
* 练习:
* 1.创建员工类Employee,里面有两个属性name,age
* 2.用HashSet添加三个员工的信息,实现两个员工当名字和年龄相同,证明是同一员工,则不能添加。
* 思路:因为用对象去添加员工信息,每个对象的哈希值不同,所以即使两个员工name,age相同也能添加成功,
* 所以要解决这个问题,我们需要在员工类中重写equals和hashcode的方法,实现当两个员工name和age相同时返回同一哈希值。
*
* */
@SuppressWarnings({"all"})
public class HashSetExercise {
    public static void main(String[] args) {
        HashSet hashSet = new HashSet();
        hashSet.add(new Employee("aaa",111));
        hashSet.add(new Employee("bbb",222));
        hashSet.add(new Employee("ccc",333));
        System.out.println("===================== 添加前员工信息 =========================");
        System.out.println(hashSet);
        Scanner sc = new Scanner(System.in);
        System.out.println("输入一个员工信息姓名和年龄");
        Employee employee = new Employee(sc.next(), sc.nextInt());
        if(hashSet.add(employee)){
            System.out.println("添加成功");
        }else {
            System.out.println("添加失败");
        }
        System.out.println("===================== 添加后前员工信息 =========================");
        System.out.println(hashSet);
    }
}
@SuppressWarnings({"all"})
class Employee{
    private String name;
    private int 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;
    }
    public Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return
                "name=" + name+"\t" +"age=" + age ;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Employee employee = (Employee) o;
        return age == employee.age && Objects.equals(name, employee.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

TreeSet

留个坑,暂无内容。

Map

  • Map接口特点:

    1. Map与Collection并列存在,用于保存具有映射关系的数据:key-value。
    2. Map中的key和value可以是任何引用类型的数据,会封装到HashMap¥Node对象中。
    3. Map中的Key不允许重复。
    4. Map中的Value可以重复。
    5. Map中的key可以为null,value也可以为null,注意key为null只能有一个,value为null可以有多个。
    6. 常用String类作为Map的key
    7. key和value之间存在单向一对一的关系,即通过指定的key总能找到对应的value。

  • Map接口和常用方法:

    1. put(Object key, Object value);添加。
    2. remove(Object key);根据键删除映射关系。
    3. get(Object key);根据键获取值。
    4. size();获取元素个数。
    5. isEmpty();判断个数是否为0。
    6. clear();清除
    7. containsKey(Object key);查找键是否存在。
@SuppressWarnings({"all"})
public class MapTest {
    public static void main(String[] args) {
        new MapTest().m1();
    }
    public void m1(){
        Map map = new HashMap();
        Phone phone = new Phone();
        Phone meizu = new Phone("魅族", 998);
        Phone pinguo = new Phone("苹果", 5999.00);
        Phone xiaomi = new Phone("小米", 2399.00);
        //1. put(Object key, Object value);添加。
        map.put(meizu.getName(),meizu.getPrice());
        map.put(pinguo.getName(),pinguo.getPrice());
        map.put(xiaomi.getName(),xiaomi.getPrice());
        System.out.println(map);//结果:{苹果=5999.0, 魅族=998.0, 小米=2399.0}
        //2. remove(Object key);根据键删除映射关系。
        map.remove(pinguo.getName());
        System.out.println(map);//结果:{魅族=998.0, 小米=2399.0}
        //3. get(Object key);根据键获取值。
        System.out.println(map.get(xiaomi.getName()));//结果:2399.0
        //4. size();获取元素个数。
        System.out.println(map.size());//结果:2
        //5. isEmpty();判断个数是否为0。
        System.out.println(map.isEmpty());//结果:false
        //6. containsKey(Object key);查找键是否存在。
        System.out.println(map.containsKey(meizu.getName()));//结果:true
        //7. clear();清除
        map.clear();
        System.out.println(map);//结果:{}
    }
}
class Phone{
    private String name;
    private double price;
    public Phone() {
    }
    public Phone(String name, double price) {
        this.name = name;
        this.price = price;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    @Override
    public String toString() {
        if (this.name == null) {
            return "price=" + price;
        }
        if (this.price == 0) {
            return "name=" + name;
        }
        return "";
    }
  • Map的三种遍历方式:

@SuppressWarnings({"all"})
public class MapTraverse {
    public static void main(String[] args) {
        Map map = new HashMap();
        map.put("1","朱新宇");
        map.put("3","王少楠");
        map.put("2","陈廷伟");
        map.put("4","张志涛");
        map.put("5","付晓宇");
        map.put("6","曾磊");
        map.put("7","覃家黎");
        map.put("8","谈嘻嘻");
        new MapTraverse().test(map);
    }
    //1.用迭代器遍历Map
    public void  MapTraverse01(Map map){
        Set set = map.keySet();//获取所有的键值,放入集合
        Iterator iterator = set.iterator();//用存有键值的集合创建迭代器
        while (iterator.hasNext()) {//这里的hasNext()和next()实际上指向的就是键值
            Object key = iterator.next();//将当前指向的键值创建成一个对象
            Object value = map.get(key);//用map的get方法传入当前指向的键值对象
            System.out.println(value);
        }
    }
    //2.用for-each遍历Map
    public void  MapTraverse02(Map map){
        Set set = map.keySet();
        for (Object obj:set) {
            System.out.println(obj+":"+map.get(obj));
        }
    }
    //3.用entrySet遍历Map
    public void  MapTraverse03(Map map){
        Set entrySet = map.entrySet();
        for (Object entry:entrySet) {
            Map.Entry e = (Map.Entry) entry;
            Object key = e.getKey();
            Object value = e.getValue();
            System.out.println(key+":"+value);
        }
    }
    public void test(Map map){
        new MapTraverse().MapTraverse01(map);
        System.out.println("================================================");
        new MapTraverse().MapTraverse02(map);
        System.out.println("================================================");
        new MapTraverse().MapTraverse03(map);
    }
}

HashMap

  • HashMap小结:

    1. HashMap是Map接口中使用频率最高的。
    2. key不能重复,但是值可以重复,允许使用null键和null值。
    3. 如果添加相同的key,那么就会覆盖原来的key-val,等同于修改。
    4. 与HashSet一样,不保证映射的顺序,因为底层是以hash表的方式存储的。
    5. HashMap没有实现同步,因此线程是不安全的。

HashTable

  • HashTable介绍:

    1. 存放的元素是键值对。
    2. HashTable的键和值都不能为null。
    3. HashTable使用方法基本上和HashMap一样。
    4. HashTable是线程安全的,HashMap是线程不安全的。

Properties

  • Properties介绍:

    1. Properties类继承了HashTable类并实现了Map接口,也是一种键值对形式来保存数据。
    2. 他的使用特点和HashTable类似。
    3. Properties还可以用于从xxx.properties文件种,加载数据到Properties类对象,并进行读取和修改。

总结:

  • 在开发中选择什么样的集合实现类,取决于业务操作的特点,然后根据集合实现类的特性进行选择:

    • 先判断存储的类型(一组对象[单列集合]或一组键值对[双列集合])。

    • 一组对象[单列集合]:

      • 允许重复元素:List

        • 增删多:选LinkedList(底层维护了一个双向链表)。
        • 改查多:选ArrayList(底层维护了Object类型的可变数组)。
      • 不允许重复元素:Set

        • 无序:HashSet(底层是HashMap,维护了一个哈希表[即数组+链表+红黑树])。
        • 排序:TreeSet。
        • 插入和取出顺序一致:选LinkedHashSet(维护数组+双向链表),
    • 一组键值对[双列集合]:Map

      • 键无序:HashMap(底层是哈希表。jdk7:数组+链表,jdk8:数组+链表+红黑树)。
      • 键排序:TreeMap.
      • 键插入和取出顺序一致:LinkedHashMap。
      • 读取文件:properties。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

echo wsn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值