当前位置: 首页 > article >正文

Java 集合一口气讲完!(下)p\··/q

Java 映射

Java集合教程 - Java映射

映射表示包含的集合键值映射。

Map是一个集合,其中每个元素表示一个键值对作为<key,value> ;.<key,value> 对也称为映射中的条目。键和值必须是引用类型。

映射由 Map<K,V> 接口的实例表示,它不是继承自 Collection 接口。

映射不允许任何重复的键。每个键映射到正好一个值。值不必是唯一的。 两个键可以映射到相同的值。

Map 允许最多一个空值键和多个空值作为其值。

Map接口中的方法可以根据其执行的操作分为以下四类:

  • 基本操作
  • 批量操作
  • 查看操作
  • 比较操作

基本操作

基本方法在Map上执行基本操作,

  • 将一个条目放入映射
  • 获取指定键的值
  • 获取条目的数量
  • 删除条目
  • 检查Map是否为空。

本类别中的方法示例如下:

int size()
boolean isEmpty()
boolean containsKey (Object key)
boolean containsValue (Object value)
V  get(Object  key)
V  getOrDefault(Object key, V  defaultValue)
V  put(K  key, V  value)
V  putIfAbsent(K key, V  value)
V  remove  (Object key)
boolean remove(Object key, Object value)
boolean replace(K key, V  oldValue, V  newValue)

批量操作

映射批量操作在映射上执行批量操作,例如将条目复制到另一个Map或从映射中删除所有条目。

本类别中的方法示例如下:

void  clear()
void  putAll (Map<? extends K,  ?  extends V>  t)
void  replaceAll(BiFunction<? super K,?  super V,?  extends V>  function)

查看操作

视图操作包含三种方法。我们可以从映射中查看以下集合。

  • 所有键在一个Map中作为一个Set,
  • 所有的值作为Collection,
  • 所有<key,value>对作为Set。

本类别中的方法示例如下:

Set<K> keySet()
Collection<V> values()
Set<Map.  Entry<K,  V>>entrySet()

所有键和所有< key,value> 对在映射中始终是唯一的并作为设置视图返回。

由于映射可能包含重复值,它返回一个 Collection 视图的值。

比较操作

比较操作方法处理比较两个图的相等性。本类别中的方法示例如下:

boolean equals (Object o)
int hashCode()

实施

HashMap  LinkedHashMap ,和 WeakHashMap 是三个实现类用于 Map 界面。

HashMap 允许一个 null 值作为键和多个空值作为值。

以下代码演示了如何创建和使用 Map 接口从它的实现类 HashMap 。HashMap不保证Map中条目的任何特定的迭代顺序。

下面的代码从HashMap创建一个Map

// Create a  map using HashMap
Map<String, String>  map = new HashMap<>();
map.put("CSS", "style");

LinkedHashMap是Map接口的另一个实现类。 它使用双向链表在Map中存储条目,并保持迭代排序作为插入顺序。

以下代码演示了如何使用Map。

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

public class Main {
  public static void main(String[] args) {
    Map<String, String> map = new HashMap<>();
    map.put("CSS", "style");
    map.put("HTML", "mark up");
    map.put("Oracle", "database");
    map.put("XML", "data");

    printDetails(map);
    map.clear();
    printDetails(map);
  }

  public static void printDetails(Map<String, String> map) {
    String usage = map.get("CSS");
    System.out.println("Map: " + map);
    System.out.println("Map Size:  " + map.size());
    System.out.println("Map is empty:  " + map.isEmpty());
    System.out.println("Map contains CSS key:   " + map.containsKey("CSS"));
    System.out.println("Usage:  " + usage);
    System.out.println("removed:  " + map.remove("CSS"));
  }
}

上面的代码生成以下结果。

WeakHashMap 类是 Map 接口的另一种实现。

WeakHashMap 类包含弱键。当除了在映射中没有对键的引用时,键是垃圾回收的候选。

如果一个键被垃圾回收,它的相关条目从 WeakHashMap 中删除。

WeakHashMap 允许一个空键和多个空值。

Java 映射操作

Java集合教程 - Java映射操作

映射迭代

要迭代地图的键,值或条目,使用映射的 keySet() values() entrySet它分别返回一组键,值集合和一组条目。

以下代码段显示了如何打印映射的所有键:

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

public class Main {
  public static void main(String[] args) {
    Map<String, String> map = new HashMap<>();
    map.put("CSS", "style");
    map.put("HTML", "mark up");
    map.put("Oracle", "database");
    map.put("XML", "data");

    // Get  the   set of  keys
    Set<String> keys  = map.keySet();

    // Print all keys  using the   forEach()  method.
    keys.forEach(System.out::println);
  }
}

上面的代码生成以下结果。

映射条目

映射中的每个键值对都称为条目。条目由 Map.Entry<K,V> 接口的实例表示。

Map.Entry  Map 接口的内部静态接口。

Map.Entry 有三个方法调用 getKey() getValue() setValue()它返回条目的键值,值,并分别在条目中设置新值。

Map的条目集上的典型迭代如下:

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

public class Main {
  public static void main(String[] args) {
    Map<String, String> map = new HashMap<>();
    map.put("CSS", "style");
    map.put("HTML", "mark up");
    map.put("Oracle", "database");
    map.put("XML", "data");

    // Get the entry Set
    Set<Map.Entry<String, String>> entries = map.entrySet();

    entries.forEach((Map.Entry<String, String> entry) -> {
      String key = entry.getKey();
      String value = entry.getValue();
      System.out.println("key=" + key + ",  value=" + value);
    });

  }
}

上面的代码生成以下结果。

映射条目迭代

forEach(BiConsumer<?super K,?super V> action) Map 界面遍历映射中的所有条目。

该方法需要一个 BiConsumer 实例第一个参数是键,第二个参数是值用于映射中的当前条目。

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

public class Main {
  public static void main(String[] args) {
    Map<String, String> map = new HashMap<>();
    map.put("CSS", "style");
    map.put("HTML", "mark up");
    map.put("Oracle", "database");
    map.put("XML", "data");

    map.forEach((String key, String value) -> {
      System.out.println("key=" + key + ",  value=" + value);
    });

  }
}

上面的代码生成以下结果。

映射视图

以下代码演示了如何获取Map的三个不同视图迭代这些视图中的元素。

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

public class Main {
  public static void main(String[] args) {
    Map<String, String> map = new HashMap<>();
    map.put("CSS", "style");
    map.put("HTML", "mark up");
    map.put("Oracle", "database");
    map.put("XML", "data");

    System.out.println("Map: " + map.toString());

    listValues(map);
    listEntries(map);
  }

  public static void listKeys(Map<String, String> map) {
    System.out.println("Key Set:");
    Set<String> keys = map.keySet();
    keys.forEach(System.out::println);
    System.out.println();
  }

  public static void listValues(Map<String, String> map) {
    System.out.println("Values Collection:");
    Collection<String> values = map.values();
    values.forEach(System.out::println);
    System.out.println();
  }

  public static void listEntries(Map<String, String> map) {
    System.out.println("Entry Set:");

    // Get the entry Set
    Set<Map.Entry<String, String>> entries = map.entrySet();
    entries.forEach((Map.Entry<String, String> entry) -> {
      String key = entry.getKey();
      String value = entry.getValue();
      System.out.println("key=" + key + ",  value=" + value);
    });
  }
}

上面的代码生成以下结果。

Java 特殊类型映射 

Java集合教程 - Java特殊类型映射

已排序的映射

分类映射按顺序保存映射条目。

它基于键对映射条目进行排序从代码中的 Comparable 接口a Comparator 对象。

如果键实现 Comparable 接口并且您使用 Comparator 对象, Comparator 对象会做排序。

SortedMap 接口继承了Map接口表示排序的映射。

Comparator comparator()
返回用于在SortedMap中进行自定义排序的 Comparator 对象。

K firstKey()返回SortedMap中第一个条目的键。如果SortedMap为空,它会抛出一个 NoSuchElementException 

SortedMap headMap(K toKey)返回其条目的SortedMap的视图将具有小于指定的toKey的键。视图由原始SortedMap支持。

K lastKey()返回SortedMap中最后一个条目的键。如果SortedMap为空,它会抛出一个NoSuchElementException异常。

SortedMap subMap(K fromKey,K toKey)返回SortedMap的视图其条目将具有从指定的键fromKey(包含)和toKey(exclusive)。

SortedMap tailMap(K fromKey)返回其条目的SortedMap的视图将具有等于或大于指定的fromKey的密钥。

TreeMap 类是实现类 SortedMap 界面。下面的代码演示了如何使用 SortedMap 

import java.util.SortedMap;
import java.util.TreeMap;

public class Main {
  public static void main(String[] args) {
    SortedMap<String, String> sMap = new TreeMap<>();
    sMap.put("CSS", "style");
    sMap.put("HTML", "mark up");
    sMap.put("Oracle", "database");
    sMap.put("XML", "data");

    SortedMap<String, String> subMap = sMap.subMap("CSS", "XML");
    System.out.println(subMap);

    // Get the first and last keys
    String firstKey = sMap.firstKey();
    String lastKey = sMap.lastKey();
    System.out.println("First Key:  " + firstKey);
    System.out.println("Last key:   " + lastKey);
  }

}

上面的代码生成以下结果。

SortedMap与Comparator

要使用 Comparator 对象对 SortedMap 中的条目进行排序,使用 TreeMap 类的构造函数以 Comparator 作为参数。

以下代码显示了如何对基于排序映射的条目进行排序在他们的钥匙的长度随后按字母顺序键忽略情况:

import java.util.Comparator;
import java.util.SortedMap;
import java.util.TreeMap;

public class Main {
  public static void main(String[] args) {
    Comparator<String> keyComparator  = 
        Comparator.comparing(String::length).thenComparing(String::compareToIgnoreCase); 
    
    SortedMap<String, String> sMap = new TreeMap<>(keyComparator);
    sMap.put("CSS", "style");
    sMap.put("HTML", "mark up");
    sMap.put("Oracle", "database");
    sMap.put("XML", "data");

    SortedMap<String, String> subMap = sMap.subMap("CSS", "XML");
    System.out.println(subMap);

    // Get the first and last keys
    String firstKey = sMap.firstKey();
    String lastKey = sMap.lastKey();
    System.out.println("First Key:  " + firstKey);
    System.out.println("Last key:   " + lastKey);
  }

}

上面的代码生成以下结果。

可导航映射由 NavigableMap 界面的实例表示。

它通过添加方法来扩展 SortedMap 接口对于键的最接近的匹配,以相反的顺序获得映射的视图等。

TreeMap类是NavigableMap接口的实现类。

以下代码显示如何使用 NavigableMap 

import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.TreeMap;

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

    NavigableMap<String, String> nMap = new TreeMap<>();
    nMap.put("CSS", "style");
    nMap.put("HTML", "mark up");
    nMap.put("Oracle", "database");
    nMap.put("XML", "data");
    System.out.println("Navigable Map:" + nMap);

    Entry<String, String> lowerXML = nMap.lowerEntry("XML");
    Entry<String, String> floorXML = nMap.floorEntry("XML");
    Entry<String, String> higherXML = nMap.higherEntry("XML");
    Entry<String, String> ceilingXML = nMap.ceilingEntry("XML");

    System.out.println("Lower:" + lowerXML);
    System.out.println("Floor:" + floorXML);
    System.out.println("Higher:" + higherXML);
    System.out.println("Ceiling:" + ceilingXML);

    // Get the reverse order view of the map
    NavigableMap<String, String> reverseMap = nMap.descendingMap();
    System.out.println("Navigable Map(Reverse  Order):" + reverseMap);

  }

}

上面的代码生成以下结果。

并发映射

ConcurrentMap 允许我们在不锁定映射的情况下执行并发操作。

我们可以在使用其实现类创建并发映射时选择并发级别。

ConcurrentHashMap类是ConcurrentMap接口的实现类。 它们都在java.util.concurrent包中。

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class Main {
  public static void main(String[] args) {
    ConcurrentMap<String, String> cMap = new ConcurrentHashMap<>();
    cMap.put("A", "A");

    System.out.println("Concurrent Map: " + cMap);

    System.out.println(cMap.putIfAbsent("A", "1"));
    System.out.println(cMap.putIfAbsent("B", "B"));
    System.out.println(cMap.remove("A", "B"));
    System.out.println(cMap.replace("A", "B"));

    System.out.println("Concurrent Map: " + cMap);
  }
}

上面的代码生成以下结果。

Java 集合算法 

Java集合教程 - Java集合算法

列表排序

Collection类中的两个静态方法会对List进行排序。

  • sort(List list)按照由元素实现的Comparable接口定义的顺序对List中的元素进行排序。
  • sort(List list,Comparator c)使用传入的Comparator对象对元素进行排序。

我们还可以使用List接口中的sort(Comparator c)对List进行排序,而不使用Collections类。

以下代码演示了如何对 List 进行排序:

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

public class Main {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("J");
    list.add("R");
    list.add("C");
    list.add("X");

    System.out.println("List: " + list);

    // Uses Comparable implementation in String class
    // to sort the list in natural order
    Collections.sort(list);
    System.out.println("Sorted List:  " + list);

  }
}

上面的代码生成以下结果。

例子

以下代码使用List接口中的sort()方法按其元素长度的升序对列表进行排序:

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

public class Main {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("Java");
    list.add("R");
    list.add("CSS");
    list.add("XML");

    System.out.println("List: " + list);

    // Uses List.sort() method with a Comparator
    list.sort(Comparator.comparing(String::length));

    System.out.println("Sorted List:  " + list);

  }
}

上面的代码生成以下结果。

sort()方法使用修改的mergeesort算法,这是一个稳定的排序。

在稳定的排序中,相等的元素将在排序操作之后保持在它们当前的位置。

排序提供了 n*log(n)性能,其中 n 是列表中元素的数量。

搜索列表

Collections类中的两个静态binarySearch()方法在List中搜索键。

该方法使用二分搜索算法执行搜索。

int  binarySearch(List list,  T  key)
int  binarySearch(List list, T  key, Comparator c)

List 必须按升序排序,然后才能使用 binarySearch()方法。

如果在列表中找到该键,则该方法将在列表中返回其索引。

如果在列表中没有找到键,它返回( - (insertion_index)-1),其中 Math.abs(( - (insertion_index)-1))是我们可以插入这个键的索引仍然保持列表订购。

在列表中找不到键时,返回值为负值。

以下代码段显示了如何使用此方法:

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

public class Main {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("Java");
    list.add("R");
    list.add("CSS");
    list.add("XML");

    Collections.sort(list);
    System.out.println("List: " + list);

    int index = Collections.binarySearch(list, "CSS");
    System.out.println("CSS in List  is at " + index);

    index = Collections.binarySearch(list, "Javascript");
    System.out.println("Javascript in List is  at " + index);

  }
}

上面的代码生成以下结果。

由于“Javascript”不在列表中,二进制搜索返回-3。这意味着如果在列表中插入“Javascript”,它将被插入索引2,使用表达式( - ( - 2 + 1))计算。

随机播放列表

Shuffle给我们一个列表中的元素的随机排列。

来自Collections类的shuffle()方法的两个版本如下:

void  shuffle(List list)
void  shuffle(List list, Random  rnd)

以下代码显示如何使用shuffle方法。

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

public class Main {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("Java");
    list.add("R");
    list.add("CSS");
    list.add("XML");

    Collections.sort(list);
    System.out.println("List: " + list);

    Collections.shuffle(list);
    System.out.println("List: " + list);

    Collections.shuffle(list);
    System.out.println("List: " + list);
  }
}

上面的代码生成以下结果。

反向列表

我们可以使用 Collections 类的 reverse()的静态方法来反转列表中的元素。

void  reverse(List list)

以下代码显示如何使用 reverse()方法。

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

public class Main {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("Java");
    list.add("R");
    list.add("CSS");
    list.add("XML");

    Collections.sort(list);
    System.out.println("List: " + list);

    Collections.reverse(list);
    System.out.println("List: " + list);

  }
}

上面的代码生成以下结果。

交换列表项

交换交换列表中的两个元素。

Collections类的 swap()静态方法执行交换。

void  swap(List list, int i, int j)

 j 是两个元素的索引,它们必须在0和size-1之间,其中size是List的大小。

以下代码显示了如何使用这些方法对List的元素重新排序。

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

public class Main {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("Java");
    list.add("R");
    list.add("CSS");
    list.add("XML");

    Collections.sort(list);
    System.out.println("List: " + list);

    // Swap elements at indexes 1 and 3
    Collections.swap(list, 1, 3);
    System.out.println(list);

  }
}

上面的代码生成以下结果。

旋转列表

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

public class Main {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("Java");
    list.add("R");
    list.add("CSS");
    list.add("XML");

    Collections.sort(list);
    System.out.println("List: " + list);

    // Rotate elements by 2
    Collections.rotate(list, 2);
    System.out.println("After  Rotating by  2: " + list);

  }
}

上面的代码生成以下结果。

创建集合的不同视图

我们可以使用Collections类的asLifoQueue()静态方法创建Deque的LIFO队列视图:

<T> Queue<T> asLifoQueue(Deque<T>  deque)

要将Map的实现用作Set实现,请使用Collections类的 newSetFromMap()静态方法:

<E> Set<E> newSetFromMap(Map<E, Boolean>  map)

只读集合视图

当将集合传递到其他方法时,我们可以获取集合的只读视图,并且我们不希望被调用的方法修改集合。

Collections类提供了以下方法来获取不同类型集合的只读视图:

<T> Collection<T> unmodifiableCollection(Collection<?  extends T> c)
<T> List<T>  unmodifiableList(List<?  extends T> list)
<K,V> Map<K,V>  unmodifiableMap(Map<?  extends K,?  extends V>  m)
<K,V> NavigableMap<K,V> unmodifiableNavigableMap(NavigableMap<K,? extends  V>  m)
<T> Set<T> unmodifiableSet(Set<? extends T> s)
<T> NavigableSet<T> unmodifiableNavigableSet(NavigableSet<T>  s)
static <T> SortedSet<T> unmodifiableSortedSet(SortedSet<T>  s)
<K,V> SortedMap<K,V> unmodifiableSortedMap(SortedMap<K,? extends  V>  m)

我们传递一个特定类型的集合,并获得相同类型的只读集合。

集合的同步视图

我们可以使用Collections类的以下静态方法之一获取集合的同步视图。

<T> Collection<T> synchronizedCollection(Collection<T>  c)
<T> List<T>  synchronizedList(List<T> list)
<K,V> Map<K,V>  synchronizedMap(Map<K,V> m)
<K,V> NavigableMap<K,V> synchronizedNavigableMap(NavigableMap<K,V> m)
<T> NavigableSet<T> synchronizedNavigableSet(NavigableSet<T>  s)
<T> Set<T> synchronizedSet(Set<T> s)
<T> SortedSet<T> synchronizedSortedSet(SortedSet<T>  s)
<K,V> SortedMap<K,V> synchronizedSortedMap (SortedMap<K,V> m)

检查集合

泛型为集合提供编译时类型安全。

下面的代码有一个编译时错误,因为我们试图添加Integer类型值到一个只能有String值的Set。

Set<String> s = new HashSet<>();
s.add("Hello");
a.add(new Integer(1)); // A compile-time error

我们可以通过使用以下代码绕过编译器检查:

Set<String> s = new HashSet<  >();
s.add("Hello");

Set s2 = s;
s2.add(new Integer(123)); // No  runtime exception

我们可以通过使用检查的集合避免上述错误。Collection类的以下静态方法返回特定类型的已检查集合:

<E> Collection<E> checkedCollection(Collection<E>  c, Class<E>  type)
<E> List<E>  checkedList(List<E> list, Class<E>  type)
<K,V> Map<K,V> checkedMap(Map<K,V>   m, Class<K> keyType,  Class<V> valueType)
<K,V> NavigableMap<K,V> checkedNavigableMap(NavigableMap<K,V>  m, Class<K> keyType,  Class<V> valueType)
<E> NavigableSet<E> checkedNavigableSet(NavigableSet<E>  s, Class<E>  type)
<E> Queue<E> checkedQueue(Queue<E> queue, Class<E>  type)
<E> Set<E> checkedSet(Set<E> s, Class<E>  type)
<K,V> SortedMap<K,V> checkedSortedMap(SortedMap<K,V>  m, Class<K> keyType, Class<V> valueType)
<E> SortedSet<E> checkedSortedSet(SortedSet<E>  s, Class<E>  type)

下面的代码重写了上面的代码。

Set<String>  checkedSet = Collections.checkedSet(new HashSet<String>(),  String.class);
Set s2 = checkedSet;
s2.add(new Integer(1)); // Throws ClassCastException

创建空集合

Collections 类可以返回每种类型的不可变空集合对象。

它也可以返回一个空的迭代器。以下代码在Collections类中列出了这些静态方法:

<T> List<T>  emptyList()
<K,V> Map<K,V>  emptyMap()
<T> Set<T> emptySet()
<T> Iterator<T> emptyIterator()
<T> ListIterator<T> emptyListIterator()

Singleton集合

我们可以使用Collections类创建一个只有一个元素的集合。

我们必须创建这种集合对象,当一个方法接受一个集合作为其参数,我们只有一个对象传递给该方法。

这些方法如下:

<T> Set<T> singleton(T o)
<T> List<T>  singletonList(T o)
<K,V> Map<K,V>  singletonMap(K key,  V  value)

以下代码显示了如何使用Collections.singleton()方法。

Set<String> singletonSet  = Collections.singleton("Lonely");
// Throws a  runtime exception since a singleton set is immutable singletonSet.add("Hello");

http://www.kler.cn/a/376162.html

相关文章:

  • Rust整合Elasticsearch
  • 用Python设置、更新和获取Excel单元格的值
  • 【Linux】编辑器vim 与 编译器gcc/g++
  • 快速入门:Visual Studio 中的 Docker
  • 使用linuxdeployqt打包Qt程序问题及解决方法
  • redis做缓存,mysql的数据怎么与redis进行同步(双写一致性)
  • QNX 7.0.0开发总结
  • 【深度学习|地学应用】人工智能技术的发展历程与现状:探讨深度学习在遥感地学中的应用前景
  • 编程之路:蓝桥杯备赛指南
  • linux alsa-lib snd_pcm_open函数源码分析(三)
  • 【汽车租聘管理与推荐】Python+Django网页界面+推荐算法+管理系统网站
  • 非自适应性上下文
  • Oracle 第11章:异常处理
  • 【数据结构-邻项消除】2696. 删除子串后的字符串最小长度
  • OpenCSG传神社区月度功能更新
  • 基于SpringBoot+Vue技术的宇宙动漫网站【前后端分离】
  • 贪心算法与分数背包
  • C#版的有道智云对话接口
  • 第20课-C++【二叉搜索树】
  • 「Math」初等数学知识点大纲(占位待处理)
  • 时序数据分析:短时序分类问题
  • C++学习路线(数据库部分)二
  • 【Canal 中间件】Canal使用原理与基本组件概述
  • 前段(vue)
  • 如何解决前端发送数据到后端为空的问题
  • 【搜索引擎】俄罗斯搜索引擎yandex