Java集合类

Java类集的引出

类集实际上就属于动态对象数组,在实际开发中,数组的使用频率并不高,因为其长度固定这一特点,也成为其缺陷。为了解决此问题,Java提供了动态对象数组实现框架–Java类集框架。Java集合框架实际上就是Java针对数据结构的一种实现,而在数据结构之中,最为基础的就是链表。
思维导图

Collection 集合接口

在Java的类集里(java.util)提供了两个最为核心的接口:Collection、Map接口。
Collection是单个集合保存的最大父接口。

public intterface Collection <E> extends Iterable<E>

常用方法有:

  • public boolean add(E e);//向集合添加数据
  • public boolean addAll (Collection < ? extends E>c);//向集合添加一组数据
  • public void clean();//清空集合数据
  • public boolean contains(Object o);//查找数据是否存在,要使用equals()方法
  • public boolean remove (Object o);//删除数据,要使用equals()方法
  • public int size ();//取得集合长度
  • public Object [] toArray();//将集合变为对象数组返回
  • public Iterator < E> iterator ();//取得 Iterator接口对象,用于集合输出

使用得较多的是add()和iterator()方法,还有一点,一般来说我们不会直接使用Collection接口,它只负责给我们提供一个储存数据的标准,并不能区分存储的类型,所以更多的时候是使用它的子接口:List(允许数据重复写入),Set(不允许数据重复写入,有重复数据时不报错,但不写入)

List接口

在实际开发中,List属于高频率使用,而且它扩充了两个重要方法:

  • public E get (int index);//根据索引保存数据
  • public E set (int index,E element);//修改数据

get()方法的存在是是List的特殊之处,属于List自己扩充方法之一,在Collection接口中是没有的,List接口有三个常用的子类:

  • ArrayList //底层Array 使用90%
  • Vector //底层 Array 基本不用
  • LinkedList //底层 Link 使用频率 10%

ArrayList 子类(优先考虑)

基本操作

package practice;

import java.util.ArrayList;
import java.util.List;

public class TestDemo {
    public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("hello");//数据写入
    list.add("hello");//测试重复数据
    list.add("Jan");
    System.out.println(list);//打印
    System.out.println(list.get(2));//get测试,取Jan
    System.out.println(list.set(0, "morning"));//修改0号元素
    System.out.println(list.size());//长度获取
    System.out.println(list);//再次打印
    System.out.println(list.contains("Jan"));//数据查找
    System.out.println(list.contains("jan"));//数据查找
    list.clear();//清空
    System.out.println(list);//打印结果

    }
}
//++++++++++++++++++++++++++++++++++++++
Result:
[hello, hello, Jan]
Jan
hello
3
[morning, hello, Jan]
true
false
[]

现在将List<String> list = new ArrayList<>();替换成Collection<String> list = new ArrayList<>(); 可以发现,代码中的get()、set()报错,因为这两个方法是List扩展的,在Collection中并没有,但是其他方法依然可以用。

package practice;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class TestDemo {
    public static void main(String[] args) {
//  List<String> list = new ArrayList<>();
    Collection<String> list = new ArrayList<>();
    list.add("hello");//数据写入
    list.add("hello");//测试重复数据
    list.add("Jan");
    System.out.println(list);//打印
//  System.out.println(list.get(2));//get测试,取Jan
//  System.out.println(list.set(0, "morning"));//修改0号元素
    System.out.println(list.size());//长度获取
    System.out.println(list);//再次打印
    System.out.println(list.contains("Jan"));//数据查找
    System.out.println(list.contains("jan"));//数据查找
    list.clear();//清空
    System.out.println(list);//打印结果

    }
}

//++++++++++++++++++++++++++++++++++
Result
[hello, hello, Jan]
3
[hello, hello, Jan]
true
false
[]

可以看出,List接口是Collection的子接口,所以除扩充方法外,List中的方法在Collection中依然可以使用,不过开发中依然不建议使用Collection。

集合与简单Java类

在实际开发中,集合里保存最多一般是简单Java类

class Person {
    private String name;
    private Integer age;
    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((age == null) ? 0 : age.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (age == null) {
            if (other.age != null)
                return false;
        } else if (!age.equals(other.age))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }

}
public class TestDemo{
    public static void main(String[] args) {
        List<Person> list = new ArrayList<>();
        list.add(new Person("Jan", 23));//装入数据
        list.add(new Person("Dog", 20));
        list.add(new Person("sb", 30));
        System.out.println(list);//打印一下
        list.remove(new Person("sb", 30));//删除
        System.out.println(list);//再打印一下
        System.out.println(list.contains(new Person("Dog", 20)));
    }//数据查找
}

//+++++++++++++++++++++++++++++++++
Result
[Person [name=Jan, age=23], Person [name=Dog, age=20], Person [name=sb, age=30]]
[Person [name=Jan, age=23], Person [name=Dog, age=20]]
true

值得一提的是,这里使用了remove()、contains()方法,必须要覆写equals方法,如果不覆写,上面的代码将会得到下列结果:

[Person [name=Jan, age=23], Person [name=Dog, age=20], Person [name=sb, age=30]]
[Person [name=Jan, age=23], Person [name=Dog, age=20], Person [name=sb, age=30]]
false

很容易理解,因为集合中所存放的对象都是在堆上开辟的新空间,如果不覆写equals(),仅仅比较的是地址,那么得到的结果一定是false。

古老的Vector,使用频率很低

在使用上与ArrayList并没有太大区别,将List<String> list = new ArrayList<>();改成List<String> list = new Vector<>();

public class TestDemo {
    public static void main(String[] args) {
//  List<String> list = new ArrayList<>();
    List<String> list = new Vector<>();
    list.add("hello");//数据写入
    list.add("hello");//测试重复数据
    list.add("Jan");
    System.out.println(list);//打印
    System.out.println(list.get(2));//get测试,取Jan
    System.out.println(list.set(0, "morning"));//修改0号元素
    System.out.println(list.size());//长度获取
    System.out.println(list);//再次打印
    System.out.println(list.contains("Jan"));//数据查找
    System.out.println(list.contains("jan"));//数据查找
    list.clear();//清空
    System.out.println(list);//打印结果

    }
}
//+++++++++++++++++++++++++++++++
Result
[hello, hello, Jan]
Jan
hello
3
[morning, hello, Jan]
true
false
[]

ArrayList与Vector区别

  • 产生时间:ArrayList:JDK1.2,Vector:JDK1.0。
  • 处理形式:ArrayList是异步处理,性能更高;Vector是同步处理,性能较低。
  • 数据安全:ArrayList是非线程安全;Vector是性能安全
  • 输出形式:ArrayList支持Iterator、ListIterator、foreach;Vector支持Iterator、ListIterator、foreach、Enumeration
    Vector比ArrayList多一个枚举输出Enumeration

尽管ArrayList是非线程安全,我们仍然优先考虑使用ArrayList,。如果需要考虑同步也可以使用concurrent包提供的工具将ArrayList变为线程安全的集。

linkedList子类

使用上与之前并无区别,将List<String> list = new ArrayList<>();改成List<String> list = new LinkedList<>();

public class TestDemo {
    public static void main(String[] args) {
//  List<String> list = new ArrayList<>();
//  List<String> list = new Vector<>();
    List<String> list = new LinkedList<>();
    list.add("hello");//数据写入
    list.add("hello");//测试重复数据
    list.add("Jan");
    System.out.println(list);//打印
    System.out.println(list.get(2));//get测试,取Jan
    System.out.println(list.set(0, "morning"));//修改0号元素
    System.out.println(list.size());//长度获取
    System.out.println(list);//再次打印
    System.out.println(list.contains("Jan"));//数据查找
    System.out.println(list.contains("jan"));//数据查找
    list.clear();//清空
    System.out.println(list);//打印结果

    }
}

//++++++++++++++++++++++++++++++++++++++
Result
[hello, hello, Jan]
Jan
hello
3
[morning, hello, Jan]
true
false
[]

输出结果也没有任何变化
ArrayList与LinkedList区别
ArrayList底层为数组,而LinkedList底层为链表,区别进而变为数组与链表的区别,性能,空间利用率等。

Set集合

Set接口与List的最大区别是不允许数据重复,以及没有get(),set()方法的扩充。
Set接口的两个常用子类HashSet(无序存储)、TreeSet(有序存储,升序)

public class TestDemo{
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        set.add("Hello");
        set.add("Hello");
        set.add("Jan");
        System.out.println(set);
    }
}

//+++++++++++++++++++++++++++++
Result
[Hello, Jan]

当进行重复数据写入时,并没报错,但是从打印结果上可以发现,重复内容并没有被写入,而是被自动跳过了。

再来看一看顺序:

public class TestDemo{
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        set.add("Jan");
        set.add("J");
        set.add("a");
        set.add("n");
        System.out.println(set);
    }
}
//+++++++++++++++++++++++++++++
Result
[a, Jan, J, n]

如果按照数据写入顺序,打印结果因该是[Jan,J,a,n],然而结果却不是如此,这就是前面所说的无序。
而如果用TreeSet():

public class TestDemo{
    public static void main(String[] args) {
        Set<String> set = new TreeSet<>();
        set.add("J");
        set.add("A");
        set.add("N");
        set.add("j");
        set.add("a");
        set.add("n");
        System.out.println(set);
    }
}

//+++++++++++++++++++++++++++++++++++++
Result
[A, J, N, a, j, n]

可以看出,这儿的输入内容已经被排序了。

TreeSet排序分析

和前面所提的类似,如果要排序对象,那么就要实现Comparable接口,并覆写compareTo()方法。

class Person implements Comparable<Person>{
    private String name;
    private Integer age;
    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public int compareTo(Person o) {
        if (this.age > o.age ) {
            return 1 ;
        }else if (this.age < o.age ){
            return -1 ;
        }else {
        return this.name.compareTo(o.name) ;
        }
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

}
public class TestDemo{
    public static void main(String[] args) {
        Set<Person> set = new TreeSet<>();
        set.add(new Person("Jan", 23));
        set.add(new Person("Dog", 20));
        set.add(new Person("Dog", 20));
        set.add(new Person("sb", 40));
        System.out.println(set);
    }
}

//+++++++++++++++++++++++++++++++++++++
Result
[Person [name=Dog, age=20], Person [name=Jan, age=23], Person [name=sb, age=40]]

从打印结果可以看到,结果被排序了,如果不实现接口Comparable,覆写compareTo()方法,结果就不一样。

重复元素判断

如果是HashSet子类,判断重复元素依靠的是Object 中的两个方法:

  • hashCode()
  • equals()
class Person implements Comparable<Person>{
    private String name;
    private Integer age;
    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((age == null) ? 0 : age.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (age == null) {
            if (other.age != null)
                return false;
        } else if (!age.equals(other.age))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
    @Override
    public int compareTo(Person o) {
        if (this.age > o.age ) {
            return 1 ;
        }else if (this.age < o.age ){
            return -1 ;
        }else {
        return this.name.compareTo(o.name) ;
        }
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

}
public class TestDemo{
    public static void main(String[] args) {
//      Set<Person> set = new TreeSet<>();
        Set<Person> set = new HashSet<>();
        set.add(new Person("Jan", 23));
        set.add(new Person("Dog", 20));
        set.add(new Person("Dog", 20));
        set.add(new Person("sb", 40));
        System.out.println(set);
    }
}

//+++++++++++++++++++++++++++++++++++++++
Result
[Person [name=Jan, age=23], Person [name=Dog, age=20], Person [name=sb, age=40]]

如果没有覆写或者只覆写了其中一个方法都是不行的,也就是说,必须哈hashCode()和equals()同时满足条件时才成立。

在使用时:
保存自定义对象时使用List接口;
保存系统数据时使用Set接口;

另外:
HashSet可以add()null,有且只能放一个,而TreeSet不能放null(java.lang.NullPointerException)。

集合输出

  • Iterator
  • ListIterator
  • Enumeration
  • foreach

迭代输出:Iterator(标准输出)

只要有Collection接口的子类对象,就一定有一个Iterator()取得Iterator实例化对象用于集合输出。
Iterator接口里有三个抽象方法:

  • 判断是否有下一个元素: public boolean hasNext();
  • 取得当前元素: public E next();
  • 删除元素: public default void remove(); 此方法从JDK1.8开始变为default完整方法。

public class TestDemo{
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Hello");
        list.add("Jan");
        list.add("Dog");
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {//判断下一个元素是否存在
            String string = (String) iterator.next();//取得当前元素
            System.out.println(string);
        }
        System.out.println("+++++++++++++++++++++++++++++++++++");
        for (String string : list) {
            System.out.println(string);
        }
    }
}
//++++++++++++++++++++++++++++++++++++
Result
Hello
Jan
Dog
+++++++++++++++++++++++++++++++++++
Hello
Jan
Dog

在遍历时删除元素,遍历时使用集合提供的remove()方法

public class TestDemo{
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Hello");
        list.add("Jan");
        list.add("Dog");
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {//判断下一个元素是否存在
            String string = (String) iterator.next();//取得当前元素
            list.remove("Hello");
            System.out.println(string);
        }
    }
}

//++++++++++++++++++++++++++++++
Result
java.util.ConcurrentModificationException

这个错误产生的原因为,在集合内部有一个ModCount记录修改次数(版本),在遍历时,修改了其中内容,ModCount与遍历之前的ModCount不一致,就会产生java.util.ConcurrentModificationException异常。
将代码修改,使用Iterator提供的remove()

public class TestDemo{
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Hello");
        list.add("Jan");
        list.add("Dog");
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {//判断下一个元素是否存在
            String string = (String) iterator.next();//取得当前元素
//          list.remove("Hello");
            if(string.equals("Hello")) {
            iterator.remove();
            continue;
            }
            System.out.println(string);
        }
    }
}

//++++++++++++++++++++++++++++++++++++
Result
Jan
Dog

使用Iterator提供的remove()不会修改ModCount,所以不会产生java.util.ConcurrentModificationException异常。
但是,仍然不建议在集合输出是进行数据修改,如果在多线程中,问题尤为明显。

双向迭代接口:ListIterator

接口提供了连个方法:

  • 判断是否有上一个元素:public boolean hasPrevious();
  • 取得上一个元素:public E previous();
public class TestDemo{
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Hello");
        list.add("Jan");
        list.add("Dog");
        ListIterator<String> listIterator = list.listIterator();
        while (listIterator.hasNext()) {
            System.out.println(listIterator.next());
        }
        System.out.println("+++++++++++++++Divide+++++++++++++++++++++");
        while (listIterator.hasPrevious()) {
            System.out.println(listIterator.previous());
        }
    }
}

//+++++++++++++++++++++++++++++++++
Result
Hello
Jan
Dog
+++++++++++++++Divide+++++++++++++++++++++
Dog
Jan
Hello

双向迭代的特点就是即可以从前往后输出,又可以从后往前输出,但是值得注意的是,要想从后往前输出的前提是先要从前往后输出。,如果没有进行从前往后的输出就进行从后往前的输出:

public class TestDemo{
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Hello");
        list.add("Jan");
        list.add("Dog");
        ListIterator<String> listIterator = list.listIterator();
//      while (listIterator.hasNext()) {
//          System.out.println(listIterator.next());
//      }
        System.out.println("+++++++++++++++Divide+++++++++++++++++++++");
        while (listIterator.hasPrevious()) {
            System.out.println(listIterator.previous());
        }
        while (listIterator.hasNext()) {
            System.out.println(listIterator.next());
        }
    }
}

//+++++++++++++++++++++++++++++++++++++++++++++
Result
+++++++++++++++Divide+++++++++++++++++++++
Hello
Jan
Dog

则从后往前输出不会执行。

Enumeration枚举输出

Enumeration接口依赖于Vector,Enumeration定义了两个个方法

  • 判断是否有下一个元素:public boolean hasMoreElements();
  • 取得元素:public E nextElement();
public class TestDemo{
    public static void main(String[] args) {
        Vector<String> vector = new Vector<>();
        vector.add("Hello");
        vector.add("Jan");
        vector.add("Dog");
        Enumeration<String> enumeration = vector.elements();
        while (enumeration.hasMoreElements()) {
//          String string = (String) enumeration.nextElement();
//          System.out.println(string);
            System.out.println(enumeration.nextElement());
        }
    }
}

//+++++++++++++++++++++++++++++++++
Result
Hello
Jan
Dog

foreach输出

在前面其实就已经使用过了。

public class TestDemo{
    public static void main(String[] args) {
        Vector<String> vector = new Vector<>();
        vector.add("Hello");
        vector.add("Jan");
        vector.add("Dog");
        Enumeration<String> enumeration = vector.elements();
        while (enumeration.hasMoreElements()) {
//          String string = (String) enumeration.nextElement();
//          System.out.println(string);
            System.out.println(enumeration.nextElement());
        }
        for (String string : vector) {
            System.out.println(string);
        }
    }
}

//++++++++++++++++++++++++++++++++++++++++++++
Result
Hello
Jan
Dog
Hello
Jan
Dog

结果与前面的输出结果一致。
总结:

  • Iterator是集合的标准输出,集合就用它输出。

Map集合

不同于Collection的每次单个对象的保存,Map每次保存的是一对对象,Key=Value的关系。
接口定义:

public interface Map<K,V>

常用方法:
public V put (K key,V value);//向map中追加数据
public V get (Object Key);//根据Key取value,没有返回null
public Set< K> KeySet();//取得所有Key信息、Key不能重复
public Collection < V> value();//取得所有value信息,可以重复
public Set < Map.Entry< K,V>> entrySet();//将Map集合转换成Set集合

Map本身也是接口,需要用子类进行实例化,Map常用的子类有四个:

  • HashMap
  • HansTable
  • TreeMap
  • ConcurrentHashMap

HashMap

HashMap是Map集合中最常用的子类。

package map;

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

public class TestDemo {

    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<>();
        map.put(1, "Jan");
        map.put(2, "Dog");
        map.put(10, "W");//是否有序
        map.put(null, "n");//测key,value是否为null
        map.put(null, "N");
        map.put(null, null);
        map.put(3, "Cat");//检测重复value
        map.put(1, "Han");//检测重复Key
        System.out.println(map);
        System.out.println(map.get(10));//根据key取value
        System.out.println(map.get(11));
        Set<Integer> set =map.keySet();//取得所有Key
        Iterator<Integer> iterator = set.iterator();
        while (iterator.hasNext()) {
            Integer integer = (Integer) iterator.next();
            System.out.println(integer);
        }
        Collection<String> collection = map.values();//取所有value
        Iterator<String> iterator2 = collection.iterator();
        while (iterator2.hasNext()) {
            String string = (String) iterator2.next();
            System.out.println(string);
        }
        Set<Map.Entry<Integer, String>> set2 = map.entrySet();
        System.out.println(set2);
    }

}

//+++++++++++++++++++++++++++++++++++++++++
{null=null, 1=Han, 2=Dog, 3=Cat, 10=W}
W
null
null
1
2
3
10
null
Han
Dog
Cat
W
[null=null, 1=Han, 2=Dog, 3=Cat, 10=W]

根据上面代码测试,可以知道HashMap的一些特性:

  • 存入内容根据Key值排序(降序)
  • Key值可以为null
  • Value可以为null
  • Key重复时旧的Key将被更新
  • Value可以重复

    HashMap原理:
    在数据量小时(JDK1.8后阀值为8)时HashMap是按照链表模式存储,而数据量变大之后就会转用红黑树(均衡二叉树)进行数据存储,用Hash码作为数据定位。

HashTable

基本操作:

public class TestDemo{
    public static void main(String[] args) {
        Map<Integer, String> map = new Hashtable<>();
        map.put(1, "Jan");
        map.put(2, "Dog");
        map.put(1, "Han");//重复key
//      map.put(3, null);//测value
//      map.put(null, "Jan");//测key
        System.out.println(map);
    }
}
//++++++++++++++++++++++++++++++++++++++
{2=Dog, 1=Han}

与HashMap相比之,HashTable存入数据时按照降序排列的,但是对于Key、Value更为严格,都不允许null(java.lang.NullPointerException),Key重复时仍然更新旧值。
HashMap与HashTable区别

ConcurrentHashMap

ConcurrentHashMap的特点 = HashTable的线程安全 + HashMap的高性能,在使用ConcurrentHashMap处理时,即可以保证即可以保证多个线程的同步,又可以保证高效的查询速度。ConcurrentHashMap不允许Key为null。

定义:

public class ConcurrentHashMap < K,V> extends AbstractMap < K,V> implements ConcurrentHashMap < K,V>,Serializable

基本操作:

public class TestDemo{
    public static void main(String[] args) {
//      Map<Integer, String> map = new Hashtable<>();
        Map<Integer, String> map = new ConcurrentHashMap<>();
        map.put(1, "Jan");
        map.put(3, "Pig");
        map.put(2, "Dog");
        map.put(0, "zero");
        map.put(1, "Han");//重复key
//      map.put(3, null);//测value
//      map.put(null, "Jan");//测key
        System.out.println(map);
    }
}
//++++++++++++++++++++++++++++++++++++++
{0=zero, 1=Han, 2=Dog, 3=Pig}

其特性与HashMap基本一致。

工作原理:
如果采用一定的算法,将保存的大量数据平均分装不同的通(数据区域),这样查找数据就可以避免全局查找,从而提高效率。

Map集合使用Iterator输出

Map接口与Collection接口不同,Collection接口有Iterator()方法,可以很方便的取得Iterator对象来输出,而Map接口本身并没有此方法。
因此,在输出时,不能直接输出,那就借助方法实现,而Map提供了将Map集合转为Set集合的方法:

public Set < Map.Entry<K,V>> entry();

Set集合是Collection的子类,所以有Iterator。

public class TestDemo{
    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<>();
        map.put(1, "Jan");
        map.put(3, "Pig");
        map.put(2, "Dog");
//      System.out.println(map);
        //三步走
        //1.转化
        Set<Map.Entry<Integer, String>> set = map.entrySet();
        //2.获取Iterator
        Iterator<Map.Entry<Integer, String>> iterator = set.iterator();
        //输出
        while (iterator.hasNext()) {
            Map.Entry<java.lang.Integer, java.lang.String> entry = 
                    (Map.Entry<java.lang.Integer, java.lang.String>) iterator.next();
            System.out.println(entry.getKey());
            System.out.println(entry.getValue());
//          System.out.println(entry.getKey()+"="+ entry.getValue());

        }
    }
}

//++++++++++++++++++++++++++++++++++++++++++++++
1
Jan
2
Dog
3
Pig

特别注意< Map.Entry< K,V>>的用法,以及输出时需要用get()方法取出。

自定义Key

Map中的Key可以由用户自定义,但是必须覆写hashCode()与equals()方法。

class Person {
    private Integer age;
    private String name;
    public Person(Integer age, String name) {
        this.age = age;
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Person [age=" + age + ", name=" + name + "]";
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((age == null) ? 0 : age.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (age == null) {
            if (other.age != null)
                return false;
        } else if (!age.equals(other.age))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }

}
public class TestDemo{
    public static void main(String[] args) {
        Map<Person, String> map = new HashMap<>();
        map.put(new Person(20, "Jan"), "J");
        System.out.println(map);
        System.out.println(map.get(new Person(20,"Jan")));
    }
}

//++++++++++++++++++++++++++++++++++++++++
{Person [age=20, name=Jan]=J}
J

TreeMap


基本操作:

public class TestDemo{
    public static void main(String[] args) {
        Map<Integer, String> map = new Hashtable<>();
        map.put(2, "Jan");
        map.put(2, "Han");//重复Key
        map.put(1, "Dog");
        map.put(4, "cat");
//      map.put(null, "N");//Key为null
//      map.put(0, null);//Value为null

        System.out.println(map);
    }
}

//+++++++++++++++++++++
{4=cat, 2=Han, 1=Dog}

和HashMap一样,Key、Value都不允许为null,会排序(降序),重复Key会更新。
小结:

  • 有Comparable时就不再覆写hashCode()和equals()而覆写compareTo()
  • Coll 保存数据的目的一般用于输出(Iterator),Map保存数据一般一般用于数据查找(无,返回null)
  • Map使用Iterator时需要转换< Map.Entry< K,V>>
  • HashMap数据结构、HashMap与HashTable的区别

栈与队列

栈Stack 是一种先进后出的数据结构,Java中,Stack是类,只Vector的子类,常用方法:

  • public E push (E item)//入栈
  • public synchronized E pop*()//出栈
  • public synchronized E peek()//获取栈顶元素
public class TestDemo{
    public static void main(String[] args) {
        Stack<String> stack = new Stack<>();
        stack.push("Han");
        stack.push("Jan");
        stack.push("Cat");
        System.out.println(stack);
        System.out.println(stack.size());
        System.out.println(stack.peek());

    }
}
//++++++++++++++++++++++++++++++++++++++++++
[Han, Jan, Cat]
3
Cat

队列Queue则是先进先出,需要注意的是,Queue是接口,子类是LinkedList。和List共用,到底如何执行取决于前面是Queue还是List。
常用方法:add()、poll()出队,peek()取队首

public class TestDemo{
    public static void main(String[] args) {
        Queue<String> queue = new LinkedList<>();
        queue.add("Han");
        queue.add("Jan");
        queue.add("Cat");
        System.out.println(queue);
        System.out.println(queue.peek());
        queue.poll();
        System.out.println(queue);
        System.out.println(queue.size());
    }
}
//
[Han, Jan, Cat]
Han
[Jan, Cat]
2

Properties属性文件操作

Java中有一只牛股属性文件(资源文件)的定义:*.Properties文件,在这种文件里面的内容保存形式为“Key=Value”,通过ResourceBundle类读取的时候只能读取内容,要想编辑其内容则需要通过Properties类来完成,这个类专门做属性处理。
Properties是HashTable的子类

 public class Properties extends HashTable <Object,Object>

常用方法:

  • 设置属性 : public synchronized Object setProperty(String key, String value)
  • 取得属性 : public String getProperty(String key),如果没有指定的key则返回null
  • 取得属性 : public String getProperty(String key, String defaultValue),如果没有指定的key则返回默认

public class TestDemo{
    public static void main(String[] args) {
        Properties properties = new Properties();
        properties.setProperty("mn", "Jan");
        properties.setProperty("md", "Dog");
        System.out.println(properties);
        System.out.println(properties.getProperty("md"));
        System.out.println(properties.getProperty("mm"));
        System.out.println(properties.getProperty("mm", "Wrong"));
    }
}

//++++++++++++++++++++++++++++++++++++++++++
{md=Dog, mn=Jan}
Dog
null
Wrong

Properties支持IO,store()保存,load()加载
//………..

Collections工具类

Collections是一个集合操作工具类,包含有集合反转、排序等。

public class TestDemo{
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        List<String> list2 = new ArrayList<>();
        Collections.addAll(list, "C","B","A");//装入多个参数
        Collections.addAll(list2, "Yellow","Country","Bad","And","Fuck","Beauty","Nice","Java");
        System.out.println(list);
        Collections.reverse(list);//反转
        System.out.println(list);//查看结果
        Collections.sort(list2, null);//排序
        System.out.println(list2);//查看结果
    }
}
//+++++++++++++++++++++++++++++++++++++++++++++++
[C, B, A]
[A, B, C]
[And, Bad, Beauty, Country, Fuck, Java, Nice, Yellow]

如果没有实现Comparable接口,覆写compareTo()方法,则需要Collections.sort(list2, new PriceComparator()){…覆写compare()}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值