Java中的数据结构

数组

  • 数组是一个存放多个数据的容器
  • 数据是同一个类型的
  • 所有的数据是线性规则排列
  • 可通过位置索引来快速定位访问数据
  • 需明确容器长度
// 数组初始化
int[] a;  // 没有new即没有申请内存空间
int[] a = new int[2]; // 数组长度为2,且元素都为0
int[] a = new int[]{ 1, 2, 3 }; // 逐个初始化
int[] a = { 1, 2, 3 }; 

JCF

  • JCF是一个容器框架,容器框架是为了表示和操作容器而规定的一种标准体系结构
  • 容器是能够存储数据的空间结构:如数组、列表、散列集等
  • 容器框架主要有以下三个部分
  • 对外的接口:容器中所能存储的抽象数据类型
  • 接口的实现:可复用的数据结构
  • 算法:对数据的查找和排序

在Java1.2以后Java推出了JCF

JCF主要是实现类:

  • 列表(List、ArrayList、LinkedList)
  • 集合(Set、HashSet、TreeSet、LinkedHashSet)
  • 映射(Map、HashMap、TreeMap、LinkedHashMap)

JCF主要的算法类

  • Arrays:对数组进行查找和排序等操作
  • Collections:对Collection及其子类进行排序和查找操作

列表List

List主要实现:

  • ArrayList(非同步的)
  • LinkedList(非同步的)
  • Vector(同步)

ArrayList

  • 以数组实现的列表,不支持同步
  • 利用索引位置可以快速定位访问
  • 不适合指定位置的插入、删除的操作
  • 适合变动不大,主要用于查询的数据
  • 和Java数组相比,其容量可动态调整的
  • ArrayList在元素填满容器时会自动扩充容器大小的50%
public static void main(String[] args) {
    ArrayList<Integer> list = new ArrayList<>();
    list.add(3);
    list.add(2);
    list.add(1);
    list.add(4);
    list.add(5);
    list.add(new Integer(6));

    System.out.println(list.get(3));
    // 删除第4个元素,后面的元素会往前挪动
    list.remove(3);
    // 将9插入到第3个元素,后面元素会往后挪动
    list.add(3, 9);
}
遍历性能测试:
public static void main(String[] args) {
    ArrayList<Integer> list = new ArrayList<>(1000000);
    for (int i = 0; i < 1000000; i++) {
        list.add(i);
    }
    // 使用迭代器遍历
    traverseByIterator(list);
    // 按位置索引遍历
    traverseByIndex(list);
    // for-earch遍历
    traverseByFor(list);
}

private static void traverseByFor(ArrayList<Integer> list) {
    long startTime = System.nanoTime();
    for (Integer item : list) {
        ;
    }
    long endTime = System.nanoTime();
    System.out.println("for-earch遍历用时: " );
    System.out.println( (endTime - startTime) + "纳秒");
}

private static void traverseByIndex(ArrayList<Integer> list) {
    long startTime = System.nanoTime();
    for (int i = 0; i < list.size(); i++) {
        list.get(i);
    }
    long endTime = System.nanoTime();
    System.out.println("索引遍历用时: ");
    System.out.println( (endTime - startTime) + "纳秒");
}

private static void traverseByIterator(ArrayList<Integer> list) {
    long startTime = System.nanoTime();
    Iterator<Integer> iterator = list.iterator();
    while (iterator.hasNext()) {
        iterator.next();
    }
    long endTime = System.nanoTime();
    System.out.println("迭代器遍历用时: ");
    System.out.println( (endTime - startTime) + "纳秒");
}
运行结果:

迭代器遍历用时:
6505100纳秒
索引遍历用时:
4729700纳秒
for-earch遍历用时:
8569100纳秒

Process finished with exit code 0

LinkedList

  • 以双向链表实现的列表,不支持同步
  • 可被当作堆栈、队列和双端队列进行操作
  • 顺序访问高效、随机访问较差、中间插入和删除高效
  • 适用于经常变化的数据
public static void main(String[] args) {
    LinkedList<Integer> list = new LinkedList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    list.add(4);
    list.add(5);
    list.add(6);
    // 在头部增加9
    list.addFirst(9);
    // 将10插入到第四个元素,四以后的元素往后挪
    list.add(3, 10);
    // 将第四个元素删除
    list.remove(3);
    System.out.println(list.size());
}
遍历性能测试
public static void main(String[] args) {
    LinkedList<Integer> list = new LinkedList<>();
    for (int i = 0; i < 100000; i++) {
        list.add(i);
    }
    // 使用迭代器遍历
    traverseByIterator(list);
    // 使用位置索引遍历
    traverseByIndex(list);
    // 使用for-earch遍历
    traverseByFor(list);
}

private static void traverseByFor(LinkedList<Integer> list) {
    long startTime = System.nanoTime();
    for (Integer integer : list) {
        ;
    }
    long endTime = System.nanoTime();
    System.out.println("for-earch遍历用时:");
    System.out.println((endTime - startTime) + "纳秒");
}

private static void traverseByIndex(LinkedList<Integer> list) {
    long startTime = System.nanoTime();
    for (int i = 0; i < list.size(); i++) {
        list.get(i);
    }
    long endTime = System.nanoTime();
    System.out.println("位置索引用时:");
    System.out.println((endTime - startTime) + "纳秒");
}

private static void traverseByIterator(LinkedList<Integer> list) {
    long startTime = System.nanoTime();
    Iterator<Integer> interator = list.iterator();
    while (interator.hasNext()) {
        interator.next();
    }
    long endTime = System.nanoTime();
    System.out.println("迭代器遍历用时:");
    System.out.println((endTime - startTime) + "纳秒");
}
运行结果:

迭代器遍历用时:
6294100纳秒
位置索引用时:
3135172200纳秒
for-earch遍历用时:
6656100纳秒

Vector

  • 和ArrayList类似,可变数组实现的列表
  • Vector同步,适合在多线程下使用
  • 官方文档建议在非同步情况下,优先采用ArrayList
public static void main(String[] args) {
    Vector<Integer> vector = new Vector<>();
    vector.add(1);
    vector.add(2);
    vector.add(3);
    vector.add(4);
    vector.add(1,3);
    System.out.println(vector.size());

}
遍历性能测试
public static void main(String[] args) {
    Vector<Integer> vector = new Vector<>();
    for (int i = 0; i < 100000; i++) {
        vector.add(i);
    }
    // 使用迭代器遍历
    traverseByIterator(vector);
    // 使用位置索引遍历
    traverseByIndex(vector);
    // 使用for-earch遍历
    traverseByFor(vector);
}

private static void traverseByFor(Vector<Integer> list) {
    long startTime = System.nanoTime();
    for (Integer integer : list) {
        ;
    }
    long endTime = System.nanoTime();
    System.out.println("for-earch遍历用时:");
    System.out.println((endTime - startTime) + "纳秒");
}

private static void traverseByIndex(Vector<Integer> list) {
    long startTime = System.nanoTime();
    for (int i = 0; i < list.size(); i++) {
        list.get(i);
    }
    long endTime = System.nanoTime();
    System.out.println("位置索引用时:");
    System.out.println((endTime - startTime) + "纳秒");
}

private static void traverseByIterator(Vector<Integer> list) {
    long startTime = System.nanoTime();
    Iterator<Integer> interator = list.iterator();
    while (interator.hasNext()) {
        interator.next();
    }
    long endTime = System.nanoTime();
    System.out.println("迭代器遍历用时:");
    System.out.println((endTime - startTime) + "纳秒");
}
运行结果:

迭代器遍历用时:
7155600纳秒
位置索引用时:
6508500纳秒
for-earch遍历用时:
6303000纳秒

集合Set

  • 确定性:对任意对象都能判定其是否属于某个集合
  • 互异性:集合内每个元素都是不相同的,(内容互异)
  • 无序性:集合内的顺序无关
  • Java中的集合接口Set
  • HashSet (基于散列函数的集合,无序,不支持同步)
  • TreeSet (基于树结构的集合,可排序的、不支持同步)
  • LinkedHashSet(基于散列函数和双向链表的集合,可排序,不支持同步)

HashSet

  • 基于HashMap实现的,可容纳null元素,不支持同步
  • 支持同步使用 Set set = Collections.synchronizedSet(new HashSet(…))
  • add 添加一个元素
  • clear 清除整个HashSet
  • contains 判定是否包含一个元素
  • remove 删除一个元素
  • retainAll 计算两个集合交集
public static void main(String[] args) {
    HashSet<Integer> hashSet = new HashSet<>();
    hashSet.add(null);
    hashSet.add(10);
    hashSet.add(9);
    hashSet.add(8);
    hashSet.add(7);
    hashSet.add(6);
    // 由于以下元素重复所以插入到集合中无效
    hashSet.add(6);
    hashSet.add(null);
    System.out.println("HashSet size is " + hashSet.size()); // 6
    System.out.println(hashSet);
    // 移除元素6
    hashSet.remove(6);
    System.out.println(hashSet);
}
运行结果:

HashSet size is 6
[null, 6, 7, 8, 9, 10]
[null, 7, 8, 9, 10]

遍历性能测试:
public static void main(String[] args) {
    HashSet<Integer> hashSet = new HashSet<>();
    for (int i = 0; i < 10000; i++) {
        hashSet.add(i);
    }
    traverseByIterator(hashSet);
    traverseByFor(hashSet);
}

private static void traverseByFor(HashSet<Integer> hashSet) {
    long startTime = System.nanoTime();
    for (Integer item : hashSet) {
        ;
    }
    long endTime = System.nanoTime();
    System.out.println("for-earch遍历: ");
    System.out.println((endTime - startTime) + "纳秒");
}

private static void traverseByIterator(HashSet<Integer> hashSet) {
    long startTime = System.nanoTime();
    Iterator<Integer> integerIterator = hashSet.iterator();
    while (integerIterator.hasNext()) {
        integerIterator.next();
    }
    long endTime = System.nanoTime();
    System.out.println("迭代器遍历: ");
    System.out.println((endTime - startTime) + "纳秒");
}
运行结果:

迭代器遍历:
1592900纳秒
for-earch遍历:
1032800纳秒

LinkedHashSet

  • 继承HashSet,也是基于HashMap实现的,可容纳null元素
  • 不支持同步
  • Set set = Collections.synchronizedSet(new LinkedHashSet(…))
  • 方法和HashSet基本一致
  • add、clear、contains、remove、size
  • 通过一个双向链表维护插入顺序
public static void main(String[] args) {
    LinkedHashSet<Integer> integers = new LinkedHashSet<>();
    integers.add(null);
    integers.add(1);
    integers.add(2);
    integers.add(3);
    // 以下重复元素插入无效
    integers.add(3);
    integers.add(null);
    System.out.println(integers.size()); // 4
}
遍历性能测试:
public static void main(String[] args) {
    LinkedHashSet<Integer> integers = new LinkedHashSet<>();
    for (int i = 0; i < 10000; i++) {
        integers.add(i);
    }
    traverseByIterator(integers);
    traverseByFor(integers);
}

private static void traverseByFor(LinkedHashSet<Integer> hashSet) {
    long startTime = System.nanoTime();
    for (Integer item : hashSet) {
        ;
    }
    long endTime = System.nanoTime();
    System.out.println("for-earch遍历: ");
    System.out.println((endTime - startTime) + "纳秒");
}

private static void traverseByIterator(LinkedHashSet<Integer> hashSet) {
    long startTime = System.nanoTime();
    Iterator<Integer> integerIterator = hashSet.iterator();
    while (integerIterator.hasNext()) {
        integerIterator.next();
    }
    long endTime = System.nanoTime();
    System.out.println("迭代器遍历: ");
    System.out.println((endTime - startTime) + "纳秒");
}

TreeSet

  • TreeSet基于ThreeMap实现的,不可以容纳null元素,不支持同步
  • SortedSet set = Collections.synchronizedSortedSet(new TreeSet(…));
  • add 添加一个元素
  • clear 清空
  • contains 判定是否包含一个元素
  • remove 删除一个元素
  • 根据compareTo方法或Comparator排序
public static void main(String[] args) {
    TreeSet<Integer> treeSet = new TreeSet<>();
    treeSet.add(100);
    treeSet.add(10);
    treeSet.add(1);
    treeSet.add(12);
    treeSet.add(13);
    // 默认从小到大排序,输出为[1, 10, 12, 13, 100]
    System.out.println(treeSet);
}
遍历性能测试:
public static void main(String[] args) {
    TreeSet<Integer> treeSet = new TreeSet<>();
    for (int i = 0; i < 10000; i++) {
        treeSet.add(i);
    }
    traverseByIterator(treeSet);
    traverseByFor(treeSet);
}

private static void traverseByFor(TreeSet<Integer> hashSet) {
    long startTime = System.nanoTime();
    for (Integer item : hashSet) {
        ;
    }
    long endTime = System.nanoTime();
    System.out.println("for-earch遍历: ");
    System.out.println((endTime - startTime) + "纳秒");
}

private static void traverseByIterator(TreeSet<Integer> hashSet) {
    long startTime = System.nanoTime();
    Iterator<Integer> integerIterator = hashSet.iterator();
    while (integerIterator.hasNext()) {
        integerIterator.next();
    }
    long endTime = System.nanoTime();
    System.out.println("迭代器遍历: ");
    System.out.println((endTime - startTime) + "纳秒");
}
运行结果:

迭代器遍历:
2478900纳秒
for-earch遍历:
1279300纳秒

集合注意事项

HashSet、LinkedHashSet和TreeSet
  • HashSet,LinkedHashSet和TreeSet的元素只能是对象
  • HashSet和LinkedHashSet判定元素重复的原则
  • 判定两个元素的hashCode返回值是否相同,若不同,返回false
  • 若两者hashCode相同,判定equals方法,若不同,返回false,否则返回ture
TreeSet判定元素重复的原则
  • 需要元素继承自Compareble接口
  • 比较两个元素的compareTo方法
public class Demo5 {
    public static void main(String[] args) {
        HashSet<Cat> hashSet = new HashSet<>();
        hashSet.add(new Cat(1));
        hashSet.add(new Cat(2));
        // 由于没有重写hashCode和equals方法所以以下元素没有判定重复
        hashSet.add(new Cat(3));
        hashSet.add(new Cat(3));
        System.out.println(hashSet.size()); // 4
    }
}
class Cat {
    private int size;
    public Cat(int size) {
        this.size = size;
    }

    public int getSize() {
        return size;
    }
}
以size作为元素重复的判定依据
public class Demo5 {
    public static void main(String[] args) {
        HashSet<Cat> hashSet = new HashSet<>();
        hashSet.add(new Cat(1));
        hashSet.add(new Cat(2));
        hashSet.add(new Cat(3));
        hashSet.add(new Cat(3));
        System.out.println(hashSet.size()); // 3
    }
}
class Cat {
    private int size;
    public Cat(int size) {
        this.size = size;
    }

    public int getSize() {
        return size;
    }

    @Override
    public boolean equals(Object o) {
        // 相同的对象返回ture
        if (this == o) return true;
        // 不相同类型返回ture
        if (o == null || getClass() != o.getClass()) return false;
        Cat cat = (Cat) o;
        return size == cat.size;
    }

    @Override
    public int hashCode() {
        return Objects.hash(size);
    }

    @Override
    public String toString() {
        return "Cat{" +java
                "size=" + size +
                '}';
    }
}

注意:HashSet元素判定规则只与hashCode、equals方法有关,和compareTo方法无关

compareTo方法具体规则

// 如果a>0,则obj1>obj2
// 如果a==0,则obj1==obj2
// 如果a<0,则obj1<obj2
int a = obj1.compareTo(obj2);

映射Map

  • 映射Map指的是两个集合之间的元素对应关系
  • 如 { 1, “张三” } -> { key, value }
Java中的Map
  • Hashtable (同步,性能低效,适用于数据量小的场景)
  • HashMap (不支持同步,性能高效,适用于数据量大的场景)
  • Properties (同步,文件形式,适用于数据量小的场景)

Hashtable

  • key-value对,key和value都不允许为null
  • 同步,多线程安全
  • 无序的
  • 适合数据量小
  • 主要方法: clear 、contains / containsValue , containsKey , get , put , remove , size
public static void main(String[] args) {
    Hashtable<Integer, String> hashtable = new Hashtable<>();
    hashtable.put(1, "value 1");
    hashtable.put(2, "value 2");
    hashtable.put(3, "value 3");
    // 输出{3=value 3, 2=value 2, 1=value 1}
    System.out.println(hashtable);
}
遍历性能测试:
public static void main(String[] args) {
    Hashtable<Integer, String> hashtable = new Hashtable<>();
    for (int i = 0; i < 10000; i++) {
        hashtable.put(i, "test");
    }
    // 根据Entry遍历
    traverseByEntry(hashtable);
    // 根据KeySet遍历
    traverseByKeySet(hashtable);
    // 根据Enmueration遍历
    traverseByKeyEnumeration(hashtable);
}
// Enumeration接口遍历只能读取不能做其他操作
private static void traverseByKeyEnumeration(Hashtable<Integer, String> hashtable) {
    long startTime = System.nanoTime();
    Integer key;
    String value;
    Enumeration<Integer> keys = hashtable.keys();
    while (keys.hasMoreElements()) {
        key = keys.nextElement();
        value = hashtable.get(key);
    }
    long endTime = System.nanoTime();
    System.out.println("使用Enumeraton遍历:");
    System.out.println((endTime - startTime) + "纳秒");
}

private static void traverseByKeySet(Hashtable<Integer, String> hashtable) {
    long startTime = System.nanoTime();
    Integer key;
    String value;
    Iterator<Integer> integerIterator = hashtable.keySet().iterator();
    while (integerIterator.hasNext()) {
        // 获取key
        key = integerIterator.next();
        // 获取value
        value = hashtable.get(key);
    }
    long endTime = System.nanoTime();
    System.out.println("使用KeySet遍历:");
    System.out.println((endTime - startTime) + "纳秒");
}

private static void traverseByEntry(Hashtable<Integer, String> hashtable) {
    long startTime = System.nanoTime();
    Integer key;
    String value;
    Iterator<Map.Entry<Integer, String>> iterator = hashtable.entrySet().iterator();
    while (iterator.hasNext()) {
        Map.Entry<Integer, String> entry = iterator.next();
        // 获取key
        key = entry.getKey();
        // 获取value
        value = entry.getValue();
    }
    long endTime = System.nanoTime();
    System.out.println("使用Entry遍历:");
    System.out.println((endTime - startTime) + "纳秒");
}
运行结果:

使用Entry遍历:
2537100纳秒
使用KeySet遍历:
1931300纳秒
使用Enumeraton遍历:
1332600纳秒

HashMap

  • key-value , key和value都允许为null
  • Map map = Collections.synichronizedMap(new HashMap(…));
  • 不同步,多线程不安全
  • 无序的
  • 主要方法: clear , containsValue, containsKey , get , put , remove , size
public static void main(String[] args) {
    HashMap<Integer, String> hashMap = new HashMap<>();
    hashMap.put(1, null);
    hashMap.put(null, "value is null");
    hashMap.put(2, "value is two");
    // 输出为{null=value is null, 1=null, 2=value is two}
    System.out.println(hashMap);
}
遍历性能测试:
public static void main(String[] args) {
    HashMap<Integer, String> hashMap = new HashMap<>();
    for (int i = 0; i < 100000; i++) {
        hashMap.put(i, "test");
    }
    traverseByEntry(hashMap);
    traverseByKeySet(hashMap);
}

private static void traverseByKeySet(HashMap<Integer, String> hashtable) {
    long startTime = System.nanoTime();
    Integer key;
    String value;
    Iterator<Integer> integerIterator = hashtable.keySet().iterator();
    while (integerIterator.hasNext()) {
        // 获取key
        key = integerIterator.next();
        // 获取value
        value = hashtable.get(key);
    }
    long endTime = System.nanoTime();
    System.out.println("使用KeySet遍历:");
    System.out.println((endTime - startTime) + "纳秒");
}

private static void traverseByEntry(HashMap<Integer, String> hashtable) {
    long startTime = System.nanoTime();
    Integer key;
    String value;
    Iterator<Map.Entry<Integer, String>> iterator = hashtable.entrySet().iterator();
    while (iterator.hasNext()) {
        Map.Entry<Integer, String> entry = iterator.next();
        // 获取key
        key = entry.getKey();
        // 获取value
        value = entry.getValue();
    }
    long endTime = System.nanoTime();
    System.out.println("使用Entry遍历:");
    System.out.println((endTime - startTime) + "纳秒");
}
运行结果:

使用Entry遍历:
13562900纳秒
使用KeySet遍历:
11260300纳秒

LinkedHashMap

基于双向链表的维持插入顺序的HashMap

public static void main(String[] args) {
    LinkedHashMap<Integer, String> linkedHashMap = new LinkedHashMap<>();
    linkedHashMap.put(null, "key is null");
    linkedHashMap.put(1, null);
    linkedHashMap.put(2, "key is two");
    // 输出{null=key is null, 1=null, 2=key is two}
    System.out.println(linkedHashMap);
}
遍历性能测试:
public static void main(String[] args) {
    LinkedHashMap<Integer, String> linkedHashMap = new LinkedHashMap<>();
    for (int i = 0; i < 100000; i++) {
        linkedHashMap.put(i, "test");
    }
    traverseByEntry(linkedHashMap);
    traverseByKeySet(linkedHashMap);
}

private static void traverseByKeySet(LinkedHashMap<Integer, String> hashtable) {
    long startTime = System.nanoTime();
    Integer key;
    String value;
    Iterator<Integer> integerIterator = hashtable.keySet().iterator();
    while (integerIterator.hasNext()) {
        // 获取key
        key = integerIterator.next();
        // 获取value
        value = hashtable.get(key);
    }
    long endTime = System.nanoTime();
    System.out.println("使用KeySet遍历:");
    System.out.println((endTime - startTime) + "纳秒");
}

private static void traverseByEntry(LinkedHashMap<Integer, String> hashtable) {
    long startTime = System.nanoTime();
    Integer key;
    String value;
    Iterator<Map.Entry<Integer, String>> iterator = hashtable.entrySet().iterator();
    while (iterator.hasNext()) {
        Map.Entry<Integer, String> entry = iterator.next();
        // 获取key
        key = entry.getKey();
        // 获取value
        value = entry.getValue();
    }
    long endTime = System.nanoTime();
    System.out.println("使用Entry遍历:");
    System.out.println((endTime - startTime) + "纳秒");
}
运行结果:

使用Entry遍历:
9421600纳秒
使用KeySet遍历:
9117500纳秒

TreeMap

基于红黑树的Map,可以根据key的自然排序或者compareTo方法进行排序输出

public static void main(String[] args) {
    TreeMap<Integer, String> treeMap = new TreeMap<>();
    treeMap.put(2, null);
    // 当key为null的时候运行报空指针异常
    // treeMap.put(null, "key is null");
    treeMap.put(1, "key is two");
    // 输出为{1=null, 2=key is two}
    System.out.println(treeMap);
}
遍历性能测试:
public static void main(String[] args) {
    TreeMap<Integer, String> treeMap = new TreeMap<>();
    for (int i = 0; i < 10000; i++) {
        treeMap.put(i, "test");
    }
    traverseByEntry(treeMap);
    traverseByKeySet(treeMap);
}

private static void traverseByKeySet(TreeMap<Integer, String> hashtable) {
    long startTime = System.nanoTime();
    Integer key;
    String value;
    Iterator<Integer> integerIterator = hashtable.keySet().iterator();
    while (integerIterator.hasNext()) {
        // 获取key
        key = integerIterator.next();
        // 获取value
        value = hashtable.get(key);
    }
    long endTime = System.nanoTime();
    System.out.println("使用KeySet遍历:");
    System.out.println((endTime - startTime) + "纳秒");
}

private static void traverseByEntry(TreeMap<Integer, String> hashtable) {
    long startTime = System.nanoTime();
    Integer key;
    String value;
    Iterator<Map.Entry<Integer, String>> iterator = hashtable.entrySet().iterator();
    while (iterator.hasNext()) {
        Map.Entry<Integer, String> entry = iterator.next();
        // 获取key
        key = entry.getKey();
        // 获取value
        value = entry.getValue();
    }
    long endTime = System.nanoTime();
    System.out.println("使用Entry遍历:");
    System.out.println((endTime - startTime) + "纳秒");
}
运行结果:

使用Entry遍历:
3187900纳秒
使用KeySet遍历:
4659400纳秒

Properties

  • 继承于Hashtable
  • 可以将key-value存储到文件中
  • 适用于数据量少的配置文件
  • 继承自Hashtable的方法:clear , contains / containsValue , containsKey , get , put , remove , size
  • 从文件加载的load方法 , 写入到文件的store方法
  • 获取属性 getProperty , 设置属性 setProperty
public static void main(String[] args){
    System.out.println("写入到Test.properties文件中");
    WriteProperties("Test.properties", "name", "123456");

    System.out.println("加载到Test.properties文件");
    GetAllProperties("Test.properties");

    System.out.println("从Test.properties文件加载");
    String value = GetValueByKey("Test.properties", "name");
    System.out.println("name is " + value);
}
/**
 * @param filePath    读取properteis文件名
 * @param key         需要读取的key值
 * @return String     返回key对应的value
 * */
private static String GetValueByKey(String filePath, String key) {
    Properties properties = new Properties();
    try (InputStream in = new BufferedInputStream(new FileInputStream(filePath))) {
        // 加载所有的key-value
        properties.load(in);
        String value = properties.getProperty(key);
        return value;
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}

/**
 * @param filePath    读取properties文件名
 * @return void
 * */
private static void GetAllProperties(String filePath) {
    Properties properties = new Properties();
    try (InputStream in = new BufferedInputStream(new FileInputStream(filePath))) {
        // 加载所有的key-value
        properties.load(in);
        // 获取配置文件的名字
        Enumeration enumeration = properties.propertyNames();

        while (enumeration.hasMoreElements()) {
            String strKey = (String) enumeration.nextElement();
            String strValue = (String) properties.getProperty(strKey);
            System.out.println(strKey + " : " + strValue);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

/**
 * @param filePath    写入properties文件名
 * @param key         写入properties文件的key值
 * @param value       写入properties文件的value值
 * @return void
 * */
private static void WriteProperties(String filePath, String key, String value) {
    File file = new File(filePath);
    boolean fileDoesNotExists = ! file.exists();
    if (fileDoesNotExists) {
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    Properties properties = new Properties();
    try (InputStream in = new FileInputStream(filePath)) {
        // 加载指定文件
        properties.load(in);
        OutputStream out = new FileOutputStream(filePath);
        properties.setProperty(key, value);
        properties.store(out, "update " + key + " name");
    } catch (Exception e) {
        e.printStackTrace();
    }
}
运行结果:

写入到Test.properties文件中
加载到Test.properties文件
name : 123456
从Test.properties文件加载
name is 123456

Test.properties文件中的内容

#update name name
#Sun Jun 13 22:27:45 CST 2021
name=123456

数据结构的工具类

JCF中工具类

  • 不存储数据,而是在数据容器上,实现高效操作
  • 排序、搜索
  • 工具类有:Arrays类、Collections类
Arrays类
  • 处理对象是数组
  • 排序:对数组排序,sort / parallelSort
  • 查找:从数组中查找一个元素,binarySearch
  • 批量拷贝:从源数组批量复制到目标数组,copyOf
  • 批量复制:对数组进行批量复制,fill
  • 判定两个数组内容是否相同,equals
public static void main(String[] args) {
    Random random = new Random();
    int[] array = new int[10];
    for (int i = 0; i < array.length; i++) {
        array[i] = random.nextInt() % 100;
    }
    System.out.println("排序前");
    for (int i = 0; i < array.length; i++) {
        System.out.print(array[i] + ",");
    }
    System.out.println();
    System.out.println("排序后");
    Arrays.sort(array);
    for (int i = 0; i < array.length; i++) {
        System.out.print(array[i] + ",");
    }
}
运行结果:

排序前
46,12,-95,95,-62,9,92,-44,-14,91,
排序后
-95,-62,-44,-14,9,12,46,91,92,95,

public static void main(String[] args) {
    Random random = new Random();
    int[] array = new int[10];
    for (int i = 0; i < array.length; i++) {
        array[i] = random.nextInt() % 100;
    }
    array[array.length - 1] = 999;
    // 当数组中有多个999的时候随机返回999的指定位置
    System.out.println("999的位置: " + Arrays.binarySearch(array, 999));
}
运行结果:

999的位置: 9

public static void main(String[] args) {
    int[] a = new int[10];
    Arrays.fill(a, 100);
    int[] b = new int[10];
    Arrays.fill(b, 100);
    System.out.println("两个数组内容是否相同: " + Arrays.equals(a, b));
}
运行结果:

两个数组内容是否相同: true

Collections类
  • Collections处理对象是Collection及其子类
  • 排序:对List进行排序,sort
  • 搜索:从List中搜索元素,binarySearch
  • 批量赋值:对List批量赋值,fill
  • 最大、最小:查找集合中最大 / 最小,max,min
  • 反序:将List反序排列,reverse
public static void main(String[] args) {
    ArrayList<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(12);
    list.add(2);
    list.add(9);
    // 排序
    Collections.sort(list);
    // 检索
    System.out.println("12元素所在的位置: " + Collections.binarySearch(list, 12));
    // 最大最小值
    System.out.println("最大值: " + Collections.max(list));
    System.out.println("最小值: " + Collections.min(list));
    // 反序
    Collections.reverse(list);
    System.out.println("list的反序: " + list);
}
运行结果:

12元素所在的位置: 3
最大值: 12
最小值: 1
list的反序: [12, 9, 2, 1]

对象的比较
  • 对象实现Comparable接口(需要修改对象类)
  • Arrays和Collections在进行对象sort时,自动调用该方法
  • compareTo方法 int a = obj1.compareTo(obj2);
    • obj1 > obj2 升序,obj1 < obj2 降序,obj1 == obj2相等
  • 新建Comparator(适用于对象类不可更改的情况)
  • compare方法 int compare(Person o1, Person o2);
    • o1 - o2 > 0 升序,o1 - o2 = 0 相等,o1 - o2 < 0 降序
    • Comparator比较器将作为参数提交给工具类的sort方法
public class Demo9 {
    public static void main(String[] args) {
        Person[] people = new Person[]{
                new Person(12), new Person(20), new Person(10)
        };
        Arrays.sort(people);
        for (int i = 0; i < people.length; i++) {
            System.out.println(people[i]);
        }
    }
}
class Person implements Comparable<Person> {
    private int age;
    public Person(int age) {
        this.age = age;
    }
    @Override
    public int compareTo(Person o) {
        return this.age - o.age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                '}';
    }
}
运行结果

Person{age=10}
Person{age=12}
Person{age=20}

public class Demo9 {
    public static void main(String[] args) {
        Person[] people = new Person[]{
                new Person(12), new Person(20), new Person(10)
        };
        // 使用PersonComparator比较器
        Arrays.sort(people, new PersonComparator());
        for (int i = 0; i < people.length; i++) {
            System.out.println(people[i]);
        }
    }
}
class PersonComparator implements Comparator<Person> {
    @Override
    public int compare(Person o1, Person o2) {
        return o1.getAge() - o2.getAge();
    }
}
class Person{
    private int age;
    public Person(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                '}';
    }
}
运行结果:

Person{age=10}
Person{age=12}
Person{age=20}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值