Java_集合

集合

为存储不同类型的多个对象,Java提供了一些列特殊的类,这些类可以存储任意类型的变量,且存储长度可变,这些类统称为集合。
集合可以简单的理解为一个长度可变,可以存储不同数据类型的动态数组。
1.Collection 集合中最基本的接口,一般不直接使用该接口
2.List: Collection的子接口,用于存储一组有序、不唯一的对象
3.Set:Collection的子接口,用于存储一组有序、唯一的对象
4.Map:用于存储一组键值对象,提供键到值的映射

Collection 接口是Java单列集合的根接口定义了各种具体单列集合的共性,其他单列集合直接或间接的继承该接口。

//Collection 是 Iterable的子接口,<E>表示
public interfacce Collection <E> extends Iterable<E>{

}

开发中很少直接使用Collection 基本都是使用其子接口,子接口主要有:List、Set、Queue、SortedSet

1、List 接口

列表,类似于数组,元素都是以线性的方式存储,有顺序:即存入顺序和取出顺序一致,元素可以重复。

1.1 ArrayList 是 List 接口的一个实现类,它是程序中最常见的一种集合,底层实现为一个长度可变的数组对象。

当存入元素超过数组长度时,ArrayList 会在内存中分配一个更大的数组来存储这些元素。

ArrayList 的大部分方法都是继承自父类 Collection 和 List
集合与数组一样,索引都是从 0 开始的。
因其底层实现为一个数组,在增加或删除指定位置的元素时,会创建新的数组,所以增删改查的效率不高,因此不适合做大量的增删,适合元素的查找
package study;

import java.util.ArrayList;

public class list {
    public static void main(String[] args){
        //创建集合
        ArrayList list = new ArrayList();

        //向集合中添加元素
        list.add("张三");
        list.add("李四");
        list.add("王五");

        //获取集合中元素个数
        System.out.println("集合长度:" + list.size());

        //遍历集合的元素,可以看见集合的遍历还自带中括号[]
        System.out.println("该集合为:" + list);

        //取出并打印指定位置的元素
        System.out.println("第二个元素是:" + list.get(1));

        //删除索引为2的元素,
        list.remove(2);
        System.out.println("删除索引为2的元素后:" + list);

        //将索引为1的元素替换为“李一”
        list.set(1,"李一");
        System.out.println("将索引为1的元素替换为“李一”后:" + list);
    }

}

请添加图片描述

1.2 LinkedList 是 List 接口的另一个实现类,其内部维护了一个双向链表。

链表的每一个元素都使用引用的方式记录它的前一个元素和后一个元素,从而将所有的元素连接起来。

链表拥有很高的增删效率
针对元素的增删、获取操作,LinkedList有以下方法
//当前集合的索引index处插入元素 element
void add(int index E element)

//将指定元素 o 插入到集合的开头
void addFirst(Object o)

//将指定元素添加到结尾
void addLast(Object o)



//返回集合的第一个元素
Object getFirst()

//返回集合的最后一个元素
Object getLast()



//移除并返回第一个元素
Object removeFirst()

//移除并返回最后一个
Object removeLast()


//将指定元素o添加到结尾
boolean offer(Object o)

//将指定元素o添加到开头
boolean offerFirst(Object o)

//将指定元素添加到结尾
boolean offerLast(Object o)


//获取第一个元素
Object peekFirst()

//获取最后一个元素
Object peekLast()


//移除并返回第一个元素
Object pollFirst()

//移除并返回最后一个元素
Object pollLast()

特别注意:
  • 需要链接元素到队列尾时优先用offer()
  • 查看元素优先使用peek()
  • 删除元素优先使用poll()
package study;

import java.util.LinkedList;

public class linkedList {
    public static void main(String[] args){
        //创建集合
        LinkedList link = new LinkedList();

        link.add("张三");
        link.add("李四");
        link.add("王五");
        link.add("hello");

        //获取并打印集合中的元素
        System.out.println("获取并打印集合中的元素:" + link.toString());

        //向集合中索引为3的位置插入元素
        link.add(3,"hello world");

        //向集合的首位添加元素
        link.addFirst("This is First");

        //遍历元素
        System.out.println("遍历集合link:" + link);

        //取出集合中的第一个元素
        System.out.println(link.getFirst());

        //删除集合中索引为3的元素
        link.remove(3);

        //删除集合中第一个元素
        link.removeFirst();

        //删除集合中的最后一个元素
        link.removeLast();

        System.out.println("删除第一个和最后一个后:" + link);
    }
}

请添加图片描述

2、集合遍历

实际开发中,经常需要按照某种次序,对集合中的每个元素进行遍历。JDK 提供了 Iterator 接口 和 foreach循环

2.1.1 Iterator 循环

Iterator 接口主要用于迭代访问(遍历)集合中的元素,Iterator对象也被称为迭代器。

package study;

import java.util.ArrayList;
import java.util.Iterator;

public class iterator {
    public static void main(String[] args){

        //创建集合
        ArrayList list = new ArrayList();
        //向集合中添加字符串
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");

        //获取Iterator对象
        Iterator it = list.iterator();

        //判断集合中是否存在下一个元素
        while(it.hasNext()){
            //使用next方法取出
            Object obj = it.next();
            System.out.println(obj);
        }

    }
}

使用Iterator对象遍历集合时,内部采用指针的方式来跟踪集合中的元素。
在调用 Iterator 的 next 方法之前,Iterator指针位于第一个元素之前,不指向任何元素。
第一次调用next( ) 方法时,Iterator 的指针会向后移动一位,指向第一个元素并将其返回。
第二次调用next( )方法时,Iterator的指针会指向第二个元素并将其返回。
以此类推,直至hasNext()方法返回 false 表示已经遍历完集合中的所有元素,中止对元素的遍历。

特别注意:通过 Iterator 获取 集合中的元素时,这些元素都是 Object 类型,如果需要获取特定类型的元素,需要对数据类型进行强制转换。

2.1.2 Iterator 的并发修改异常

ArrayList list = new ArrayList();

iterator it = list . iterator;
//判断集合中是否存在下一个元素
        while(it.hasNext()){
            //使用next方法取出
            Object obj = it.next();
            //删除集合中为"3"的元素
            if("1".equals(obj)){
                list.remove(obj);
            }
        }
        System.out.println(list);

请添加图片描述

  • 在使用 Iterator 对集合元素进行遍历时,如何调用了集合对象的 remove()方法删除元素,然后继续使用 Iterator 遍历元素,就会产生 “并发修改异常”。
  • ConcurrentModificationException 并发修改异常 是 Iterator 对象抛出的,出现异常的原因是集合 Iterator运行期间删除了元素,导致 Iterator 预期的迭代次数发生改变,Iterator 的迭代结果不准确。
  • 因为这个 it 对象是在删除前创建的

解决方案有两种

  1. 直接跳出循环,不需要迭代被删除元素后面的元素
    使用 “break”
//判断集合中是否存在下一个元素
        while(it.hasNext()){
            //使用next方法取出
            Object obj = it.next();
            //删除集合中为"1"的元素
            if("1".equals(obj)){
                list.remove(obj);
                break;
            }
        }
        System.out.println(list);

请添加图片描述

  1. 使用 Iterator 本身的删除方法
    it.remove( ) 该方法没有参数,直接删除当前元素
//判断集合中是否存在下一个元素
        while(it.hasNext()){
            //使用next方法取出
            Object obj = it.next();
            //删除集合中为"1"的元素
            if("1".equals(obj)){
                it.remove(obj);
               
            }
        }
        System.out.println(list);

请添加图片描述
调用 Iterator 对象 的remove( ) 方法删除元素,所导致的迭代次数变化,对于 Iterator 对象来说是可预知的。

2.2.1 foreach 循环

这是一种更简单的 for 循环,用于遍历数组或集合中的元素

for(容器中元素类型 临时变量:容器变量){
    执行语句
}

foreach 循环不需要获得集合的长度,也不需要根据索引访问集合中的元素,自动遍历集合中的元素。

package study;

import java.lang.reflect.Array;
import java.util.ArrayList;

public class foreach {
    public static void main(String[] args){
        //创建集合
        ArrayList list = new ArrayList();
        //添加字符串元素
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");

        //使用foreach 循环遍历集合
        for(Object obj:list){
            System.out.println(obj);
        }
    }
}

请添加图片描述

特别注意: foreach 循环虽然简洁,但是只能访问元素,不能进行元素修改。

3、Set 接口

Set 接口也继承自 Collection 接口,与 List 不同,Set 接口中的元素是无序的。并且以某种规则保证存入的元素不重复。

Set 接口和 List 接口存取元素的方式一样,但Set 集合中的元素是无序的。

Set 接口常见的实现类有 3 个,分别是 HashSet、LinkedHashSet、TreeSet。

  • HashSet 根据对象的哈希值确定元素在集合中的存储位置
  • LinkedHashSet 是链表和哈希表组合的数据结构
  • TreeSet 以二叉树的方式存储元素,可以对集合中的元素进行排序

3.1.1 HashSet

HashSet ( ) 是Set接口的一个实现类,存储的元素不可重复,当给HashSet ( ) 添加一个元素时,会先调用hashCode ( ) 方法确定元素的存储位置,再调用equals ( ) 方法确保该位置没有重复元素。

通过一个案例说明HashSet( )不能有重复元素以及取出顺序和存入顺序不同的特性。
package set;

import java.util.HashSet;
import java.util.Iterator;

public class hashSet {

    public static void main(String[] args){
        HashSet hset = new HashSet();
        hset.add("张三");
        hset.add("李四");
        hset.add("王五");
        hset.add("赵六");
        //向集合中添加重复的元素
        hset.add("李四");

        //获取Iterator对象
        Iterator it = hset.iterator();

        //通过while循环判断集合中是否有元素
        while(it.hasNext()){
            //调用Iterator 的next()方法获取元素
            Object obj = it.next();
            System.out.println(obj);
        }
    }
}

3.1.2 HashSet 重写equals( )和hashCode( )方法

当向集合存入元素时,要重写equals( )和hashCode( )方法,在上面这个存入元素为String 类型的变量 的案例中,String 类已经重写了equals( ) 和 hashCode( )方法。
如果我们想给集合中存入自定义类对象,就需要手动重写这两个方法。
因为equals方法,默认不重写的情况下是比较两个对象的地址是否相同。

下面通过一个案例,演示要给集合存入自定义类对象,重写hashCode()和equals()方法

package set;

import java.util.HashSet;
import java.util.Iterator;

public class hashSet {
    public static void main(String[] args){

        //创建集合对象
        HashSet hs= new HashSet();
        //创建Student对象
        Student stu1 = new Student("1","张三");
        Student stu2 = new Student("2","李四");
        Student stu3 = new Student("2","李四");
        //向集合中存入对象
        hs.add(stu1);
        hs.add(stu2);
        hs.add(stu3);

        //输出HashSet类型的集合hs的元素
        System.out.println(hs);
    }
}
class Student{
    String id;
    String name;

    //含参构造
    public Student(String id,String name){
        this.id = id;
        this.name = name;
    }

    //重写toString()方法
    @Override
    public String toString(){
        return id+":"+name;
    }

    //重写hashCode()方法
    @Override
    public int hashCode(){
        return id.hashCode();
    }

    //重写equals方法
    @Override
    public boolean equals(Object obj){
        //判断是否为同一个对象,this指代的是当前对象,obj是传进来的
        if(this == obj){
            return true;
        }

        //判断对象是否为Student类型
        if(!(obj instanceof Student)){
            return false;
        }

        //将对象转换为Student类型
        Student stu = (Student)obj;

        //判断id值是否相等
        boolean b = this.id.equals(stu.id);
        return b;
    }
}

请添加图片描述

分析:if(this == obj) 这句代码是在检查 this(也就是当前的 Student 对象)和 obj 是否是同一个对象。如果 this 和 obj 的引用指向的是内存中的同一个对象,那么 this == obj 就会返回 true。这是一种基本的引用比较,也被称为身份比较。

如果 this 和 obj 指向的是两个不同的对象,即使这两个对象的内容完全相同,this == obj 也会返回 false。这就是为什么在 equals() 方法中,除了使用 this == obj 检查两个对象是否完全相同之外,还需要进行其他的比较(例如,还比较了 Student 对象的 id 字段)来确定两个对象的内容是否相等。这种比较被称为等价比较。

其中 instanceof是Java中的二元运算符,左边是对象,右边是类;当对象是右边类或子类所创建对象时,返回true;否则,返回false。

显然,重复的元素并没有被存入。

3.2.1 LinkedHashSet

HashSet 存储的元素是无序的,如果想让元素存取顺序一致,可以使用LinkedHashSet 类,它是HashSet 的子类,与LinkedList 一样,使用双向链表维护内部元素的关系。

package set;

import java.util.Iterator;
import java.util.LinkedHashSet;

public class linkedHashSet {
    public static void main(String[] args){
        LinkedHashSet set = new LinkedHashSet();

        set.add("张三");
        set.add("李四");
        set.add("王五");

        //获取Iterator 对象
        Iterator it = set.iterator();

        //通过while循环判断集合中是否有元素
        while(it.hasNext()){
            Object obj = it.next();
            System.out.println(obj);
        }
    }
}

请添加图片描述

3.3.1 TreeSet

TreeSet 是Set 接口的另一个实现类,内部采用二叉树存储元素,既可以保证没有重复元素,也可以对元素进行排序。
特点: 左子树<根节点<右子树 ,对于同一层的元素。 左边的元素总是<右边的元素

TreeSet 特有的方法
Object first() 返回集合的第一个元素

Object last() 返回集合最后一个元素

Object lower(Object o) 返回集合中小于给定元素 o 的最大元素,如果没有就返回null

Object floor(Obejct o) 返回集合中小于或等于 指定元素 o 的最大元素,如果没有就返回null

Object higher(Object o) 返回集合中大于给定元素 o 的最小元素,如果没有就返回null

Object ceiling(Object o) 返回集合中大于或等于给定元素 o 的最小元素,如果没有就返回null

Object pollFirst() 移除并返回集合的第一个元素

Object pollLast() 移除并返回最后一个元素

 
常可以看到这种形式的方法定义,开始不太明白含义,特此查了一下:

Object first() 是一个方法声明的形式。这里是它的各个部分的含义:

1. Object 是方法的返回类型。这意味着这个方法会返回一个 Object 类型的值。
2. first 是方法的名称。
3. () 表示这个方法没有参数。
下面通过一个案例来演示TreeSet常用方法的使用
package set;

import java.util.TreeSet;

public class treeSet {
    public static void main(String[] args){
        //创建集合
        TreeSet ts = new TreeSet();

        //向集合中添加元素
        ts.add(3);
        ts.add(29);
        ts.add(101);
        ts.add(21);

        //输出集合
        System.out.println("创建的TreeSet 集合为:" + ts);
        //可以看见输出的是有序

        //获取首尾元素
        System.out.println("首尾元素分别为:" + ts.first() +","+ ts.last());

        //比较并获取元素
        System.out.println("集合中 <=9 的最大元素为:" + ts.floor(9));
        System.out.println("集合中 >10 的最小元素为:" + ts.higher(10));
        System.out.println("集合中 >100 的最小元素为:" +ts.higher((100)));

        //删除元素
        Object first = ts.pollFirst();
        System.out.println("删除并返回集合的第一个元素:" + first);
        Object last = ts.pollLast();
        System.out.println("删除并返回集合的最后一个元素:" + last);
        System.out.println("删除后遍历:" + ts);
    }
}

请添加图片描述

不论以何种顺序插入元素,最终输出都是有序的。因为每次插入时,都会调用compareTo( ) 方法,进行比较。
该方法是在Compareable接口中定义的,因此要想对集合中的元素进行排序,就必须实现Comparable 接口。Java中大部分类 实现了Comparable 接口,默认实现接口中的CompareTo( ) 方法,比如Integer Double String 等。
但有时向TreeSet集合中存入自定义类型的数据时,比如Student、Teacher类型的数据,由于这些自定义类型的数据没有实现Comparable( ) 接口,因此无法直接在TreeSet 集合进行排序操作。
为此Java 提供了两种TreeSet集合的排序规则,分为自然排序和自定义排序。默认情况下TreeSet 集合使用自然排序。

3.3.2 自然排序

自然排序要求向 TreeSet 集合中存储的元素所在的类必须实现Comparable接口,并重写compareTo ()方法,然后 TreeSet集合就会对该类型的元素使用compareTo( ) 方法比较。

compareTo( ) 方法将当前对象与指定的对象按顺序进行比较,返回值为一个整数,其中返回负整数,零,正整数,分别表示当前对象小于,等于,大于指定对象,默认根据比较结果顺序排列。

package set;

import java.util.TreeSet;

public class Example1 {
    public static void main(String[] args){

        TreeSet ts = new TreeSet();
        ts.add(new Student("Lucy",18));
        ts.add(new Student("Tom",20));
        ts.add(new Student("Bob",20));
        ts.add(new Student("Tom",20));

        System.out.println(ts);

    }
}

class Student implements Comparable{
    private String name;
    private int age;
    public Student(String name,int age){
        this.name = name;
        this.age = age;
    }

    //重写toString()方法
    @Override
    public String toString(){
        return name + ":" + age;
    }

    //重写Comparable接口的compareTo()方法
    @Override
    public int compareTo(Object obj){
        Student stu = (Student) obj;
        //定义比较方式,先比较age再比较name
        if(this.age - stu.age>0){
            return 1;
        }
        if(this.age - stu.age == 0){
            return this.name.compareTo(stu.name);
        }
        return -1;
    }
}

请添加图片描述

3.3.3 自定义排序

如果不想实现Comparable接口或者不想按照实现Comparable接口 的 类中compareTo( ) 方法的规则进行排序,可以通过自定义比较器的方式对TreeSet 集合中的元素自定义排序规则。

实现Comparator 接口的类都是一个自定义比较器,可以在自定义比较器的compare( ) 方法中自定义排序规则。

4. Map接口

Map接口借鉴了数学中函数的思想,Map接口的每个元素都是由键到值的映射。
即Map接口中的每个元素都是由一个键值对组成

4.1 Map 接口简介

Map 接口是一种双列集合,每个元素都包含一个键对象Key和一个值对象Value,键和值之间的对应关系称为映射。
Map中的键不允许重复,访问Map集合中的元素时,只要指定了键,就能找到对应的值。
Map接口定义了一系列方法用于访问元素,常用方法如下
//将指定的值和键存入集合并进行映射关联
void put(Object key,Object value) 

//返回指定的键映射的值,如果此映射不包含该键的映射关系,则返回null
Object get(Object key)

//移除所有的键值对元素
void clear()

//根据键删除对应的值,返回被删除的值
V remove(Object key)

//返回集合中的键值对的个数
int size()

//如果此映射包含指定键的映射关系,则返回true
boolean containsKey(Object key)

//如果此映射将一个或多个键映射到指定值,则返回true
boolean containsValue(Object value)

//返回此映射中包含的键的Set集合
Set keySet()

//返回此映射中包含的值的Collection 集合
Collection <V> values()

//返回此映射中包含的映射关系的Set集合
Set<Map.Entry <K,V> >entrySet()

4.2.1 HashMap

HashMap 是 Map接口的一个实现类,HashMap 中的大部分方法都是Map接口方法的实现。

在开发中,通常把HashMap集合对象的引用赋值给Map接口变量,接口变量就可以调用HashMap 类实现的接口方法。
HashMap集合用于存储键值映射关系,但HashMap集合没有重复的键并且元素无序。

package map;

import java.util.HashMap;
import java.util.Map;

public class Example1 {
    public static void main(String[] args){
        //创建HashMap集合
        Map map = new HashMap();
        //存储键和值
        map.put("1","张三");
        map.put("2","李四");
        map.put("3","王五");

        //根据键获取值
        System.out.println("1:" + map.get("1"));
        System.out.println("2:" + map.get("2"));
        System.out.println("3:" + map.get("3"));
    }

}


请添加图片描述

HashMap集合中的键具有唯一性,现在向map中存储一个相同的键
package map;

import java.util.HashMap;
import java.util.Map;

public class Example1 {
    public static void main(String[] args){
        //创建HashMap集合
        Map map = new HashMap();
        //存储键和值
        map.put("1","张三");
        map.put("2","李四");
        map.put("3","王五");
        map.put("3","赵六");

        //根据键获取值
        System.out.println("1:" + map.get("1"));
        System.out.println("2:" + map.get("2"));
        System.out.println("3:" + map.get("3"));
    }

}


请添加图片描述

可以看见第二次添加的值,覆盖了原有的值,简而言之:键相同,值覆盖

4.2.2 取出HashMap 集合中所有的键和值

在开发中取出HashMap 集合中所有的键和值时,有两种方式。

第一种方式就是先便利HashMap 集合中所有的键,再根据键获取对应的值。
package map;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Example1 {
    public static void main(String[] args){
       //创建HashMap集合
        Map map = new HashMap();
        //存储键和值
        map.put("1","张三");
        map.put("2","李四");
        map.put("3","王五");

        //获取键的集合
        Set keySet = map.keySet();
        //获取Iterator对象
        Iterator it = keySet.iterator();

        while(it.hasNext()){
            Object key = it.next();
            //获取每个键对应的值
            Object value = map.get(key);
            System.out.println(key + ":" + value);
        }
    }

}

首先使用iterator( ) 方法遍历map集合中所有的键,再根据键获取对应的值,首先调用map对象的KeySet( ) 方法,获得map中所有键的Set集合,然后通过Iterator遍历上述Set集合中的每一个元素,即每一个键,最后调用get()方法,根据键值取对应的值。

请添加图片描述

第二种是先获取集合中所有的映射关系,然后从映射关系中取出键和值。

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Example1 {
    public static void main(String[] args){
        //创建HashMap集合
        Map map = new HashMap();
        //存储键和值
        map.put("1","张三");
        map.put("2","李四");
        map.put("3","王五");
        //map对象中的entrySet()方法获得Set集合,Set集合中存放Map.Entry类型
        //的元素(Entry是Map的内部接口),每个Map.Entry对象代表集合中的一个键值对
        Set entrySet = map.entrySet();
        //获取Iterator对象
        Iterator it = entrySet.iterator();

        while(it.hasNext()){
            //获取集合中键值对映射关系
            Map.Entry entry = (Map.Entry)(it.next());
            //获取entry中的键
            Object key = entry.getKey();
            //获取entry中的值
            Object value = entry.getValue();
            System.out.println(key+":"+value);
        }
    }
}

首先调用Map对象的entrySet()方法获得Set集合,Set集合中存放Map.Entry类型的元素,(Entry是Map的内部接口),每个Map.Entry对象代表集合中的一个键值对。然后遍历Set集合,获得每一个映射对象,并分别调用映射对象的getKey()和getValue()方法获取键和值。

4.2.3 HashMap中一些操作集合的常用方法

values()用于获取集合中所有的值,返回值类型为Collection
size()用于获取集合的大小
containsKey()用于判断是否包含传入的键
containsValue()用于判断是否包含传入的值
remove()用于根据key移除集合中的与该键对应的值

4.3.1 LinkedHashMap

HashMap集合遍历元素顺序与存入顺序不一致,如何想让集合中元素遍历顺序与存入顺序一致,可以使用LinkedHashMap集合。LinkedHashMap 是HashMap的子类。LinkedHashMap集合使用双向链表维护内部元素的关系。

package map;

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

public class Example2 {
    public static void main(String[] args){
        //创建LinkedHashMap集合
        Map map = new LinkedHashMap();

        map.put("3","李四");
        map.put("4","王五");
        map.put("2","赵六");

        Set keySet = map.keySet();
        Iterator it = keySet.iterator();
        while(it.hasNext()){
            Object key = it.next();
            Object value = map.get(key);
            System.out.println(key + ":" + value);
        }
    }
}

请添加图片描述
可以看见,遍历顺序和插入顺序一样

4.4.1 TreeMap

为了对集合中的元素的键进行排序,Map接口提供了一个可以对集合中元素的键进行排序的实现类——TreeMap。

import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

/**
 * @author 86181
 */
public class Example2{
    public static void main(String[] args){
        //创建TreeMap集合
        Map map = new TreeMap();
        //存储键和值
        map.put("3","李四");
        map.put("4","王五");
        map.put("2","赵六");
        map.put("3","张三");
        Set keySet = map.keySet();
        Iterator it = keySet.iterator();
        while(it.hasNext()){
            Object key = it.next();
            //获取每个键对应的值
            Object value = map.get(key);
            System.out.println(key+":" + value);
        }

    }
}

请添加图片描述
可以看见输入的元素已经按键从小到大自动排序了,并且值重复存入的整数3只有一个,第四个添加的 覆盖了第一个添加的。

TreeMap中的键必须是唯一且有序的,如果存在相同的键,后者会覆盖前者。

4.5.1 Properties

Map接口有一个实现类——Hash Table,他与HashMap类似,但HashTable是线程安全的。
HashTable类存取元素很慢,基本被HashMap取代,但HashTable有一个重要的子类——Properties,应用很广泛

Properties 用于存储字符串类型的键和值,实际开发中经常用于存储应用的配置项。例如,假设有一个文本编辑工具,要求默认背景为红色,字体大小为14px,语言为中文,其配置项如下代码所示
Backgroup-color = red
Font-size = 14px
Language = chinese

在程序中可以使用Properties集合对这些配置项进行存储

import java.util.Enumeration;
import java.util.Properties;

public class properties {
    public static void main(String[] args){
        //创建Properties集合
        Properties p = new Properties();
        p.setProperty("Background-color","red");
        p.setProperty("Font-size","12px");
        p.setProperty("Language","chinese");
        //获取Enumeration对象的所有键
        Enumeration names = p.propertyNames();
        while(names.hasMoreElements()){
            String key = (String)names.nextElement();
            //获取键对应的值
            String value = p.getProperty(key);
            System.out.println(key+"="+value);
        }
    }
}

请添加图片描述

在Properties类中,针对字符串的存取提供了两个专用的方法——setProperty()和getProperty()。

setProperty()用于将配置项的键和值添加到Properties集合中。

Enumeration names = p.propertyNames(); 通过调用Properties类的propertyNames()方法得到一个包含所有键的Enumeration对象。

在遍历所有键的时候,通过调用getProperty()方法获得键对应的值。

5.常用工具类

在实际开发中,经常需要按照某种条件对容器和数组进行查找、替换、排序、反转甚至是打乱等操作。

为此Java集合提供了两个常用的容器工具类——Collections和Arrays,这两个类提供了很多静态方法,通过静态方法完成上述操作。

5.1 Collections 工具类

它提供了大量静态的方法用于对集合中的元素进行排序、查找、修改的操作。

添加、反转、排序、打乱、交换

package tools;

import java.util.ArrayList;
import java.util.Collections;

public class collection {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        //添加元素
        Collections.addAll(list,"a","b","c","d","e","f","g","h");
        System.out.println(list);
        //反转集合
        Collections.reverse(list);
        System.out.println(list);
        //按自然顺序排序
        Collections.sort(list);
        System.out.println(list);
        //随机打乱集合
        Collections.shuffle(list);
        System.out.println(list);
        //交换首尾元素
        Collections.swap(list,0,7);
        System.out.println(list);
    }
}

请添加图片描述

Collection.max(list) Collection.min(list)查找

Collection.replaceAll(list,?,?)替换

Collection.sort(list) 排序

import java.util.ArrayList;
import java.util.Collections;

public class collection {
    public static void main(String[] args) {
        ArrayList<Integer>list = new ArrayList<>();
        Collections.addAll(list,1,-2,-3,4,5);
        System.out.println(list);
        //最大元素
        System.out.println("最大元素为:" + Collections.max(list));
        //最小元素
        System.out.println("最小元素为:" + Collections.min(list));
        //将集合中的-3用3替换
        Collections.replaceAll(list,-3,3);
        System.out.println("替换后:" + list);
        //使用二分查找前,必须保证元素有序
        Collections.sort(list);
        System.out.println("排序后:" + list);
        //查找元素 3 所在的位置
        int index = Collections.binarySearch(list,3);

        System.out.println("集合通过二分查找方法查找元素3所在索引:" + index);

    }
}

请添加图片描述

5.2 Arrays 工具类

针对数组提供了数组工具类Arrays。Arrays 工具类,提供了大量针对数组操作的静态方法。

Arrays.sort(str)排序

Arrays.toString(str)转换为字符串

package tools;
import java.util.Arrays;

public class shuzu {
    public static void main(String[] args) {
        //初始化数组
        int [] arr = {9,8,3,5,2};
        System.out.println("排序前:");
        printArray(arr);
        Arrays.sort(arr);
        System.out.println("排序后:");
        printArray(arr);
        //将数组转换为字符串输出
        System.out.println(Arrays.toString(arr));

    }

    //定义打印数组元素方法
    public static void printArray(int[] arr) {
        System.out.print("[");
        for(int i =0;i<arr.length;i++){
            System.out.print(arr[i]+" ");
        }
        System.out.println("]");
    }
}

请添加图片描述

Arrays.binarySearch()查找元素

该方法采用二分查找,因此只能对有序数组进行查找。如果不是有序数组,要先用Arrays.sort()排序

import java.util.Arrays;

public class shuzu {
    public static void main(String[] args) {
        //初始化数组
        int [] arr = {9,8,3,5,2,1,11,24,36};
        System.out.println("排序前:");
        System.out.println(Arrays.toString(arr));
        //查找元素5,因为binarySearch()使用二分查找,因此要先排序
        Arrays.sort(arr);
        System.out.println("排序后:");
        System.out.println(Arrays.toString(arr));
        System.out.println("元素5在第:" + Arrays.binarySearch(arr,5) + "位");
    }
}

请添加图片描述

Arrays.copyOfRange( int[ ] original,int from,int to) 复制元素

在开发中经常需要在不破坏原数组的情况下,使用数组中的部分元素,copyOfRange( ) 方法可以将数组中指定范围的元素复制到新的数组。

original 表示被复制数组,from 表示被复制元素的开始索引(包括),to表示被复制元素的结束索引(不包括)

package tools;
import java.util.Arrays;

public class shuzu {
    public static void main(String[] args) {
        //初始化数组
        int [] arr = {9,8,3,5,2};
        //复制一个指定范围的数组
        int [] copyArr = Arrays.copyOfRange(arr,0,3);
        System.out.println("原数组:" + Arrays.toString(arr));
        System.out.println("复制[0,3)后新数组:" + Arrays.toString(copyArr));
    }
}

请添加图片描述

Arrays.fill( ) 替换元素

在开发中,有时需要将一个数组中的所有元素替换成同一个元素,此时可以用Arrays.fill( ) ,该方法可以将指定的值赋给数组中的每一个元素。

package tools;
import java.util.Arrays;

public class shuzu {
    public static void main(String[] args) {
        //初始化数组
        int [] arr = {9,8,3,5,2};
        System.out.println("替换前:"+Arrays.toString(arr));
       Arrays.fill(arr,7);
        System.out.println("替换后:"+Arrays.toString(arr));

    }
}

请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值