集合2

Map接口的基本操作

Map接口的基本操作(put(),get(),containsKey(),containsValue(),size(),isEmpty())非常类似于Hashtable中相应的操作。下面程序生成一个参数列表中出现的单词的频率表。在频率表中,将每一个单词映射到它在参数列表中的次数。编写统计命令行参数字符串出现次数的程序。代码如下:

import java.util.*;
public class freq {
    public static void main(String []args){
        Map<String, Integer> m=new HashMap<String, Integer>();
        //从命令行初始化频率表
        for (String a :args){
            Integer freq=m.get(a); //获得键为a的元素的值
            //设置a出现的次数,保存在Map对象中
            m.put(a, (freq ==null)? 1:freq+1);
        }
        System.out.println(m.size()+"个不同的单词:");
        System.out.println(m);
        }
    }

上述程序需要注意的是put语句的第二个参数。该参数是一个条件表达式,用来设置一个单词出现的频率。如果这个单词从来没有出现过,则设置为1,如果已经出现过,则设置为当前值增1.

编译并运行此程序

java Freq if it is to be it is up to me to delegate

程序的输出结果如下:

8个不同的单词:
{to=3,delegate=1,be=1,it=2,up=1,if=1,me=1,is=2}

假如想按字母顺序看此频度表,那么就将Map的实现类型由HashMap改为TreeMap。将上述程序中的HashMap改为TreeMap,重新编译并以同样的命令行参数运行,输出结果如下:

8个不同的单词:
{be=1,delegate=1,if=1,is=2,it=2,me=1,to=3,up=1}

同样,若想使程序按单词在命令行参数中的顺序输出频度,只需将Map实现类型改为LinkedHashMap。那么上述程序的输出结果为:

8个不同的单词:
{if=1,it=2,is=2,to=3,be=1,up=1,me=1,delegate=1}

与Set和List接口类似,Map也加强了对equals()和hashCode()方法的要求,这样两个Map对象可以进行逻辑相等比较,而不必考虑它们的实现类型。如果两个Map实例代表相同的键值映射,那么它们就是相等的。

按惯例,所有通过的Maap实现都提供接收一个Map对象作为参数的构造方法,并初始化新的Map使其包含指定Map中所有键-值对。这个标准Map转换构造方法完全与标准Collection的构造方法类似:允许调用者创建一个希望实现的类型的Map,初始化包含另一个Map的所有映射,而不必考虑另一个映射的实现类型。例如,假设一个名为m的Map。下面这行代码创建一个新的HashMap,初始化包含m中的所有相同的键-值映射。

Map<K,V>copy =new HashMap<K,V>(m);

Map接口的批量操作

Map接口的批量操作主要有clear()方法,putAll()方法。其中clear()方法从Map中删除所有的映射,putAll()方法是Map中类似于Collection接口的addAll()方法。

putAll除了将一个Map填充进另一个Map外,它还有第二种更为巧妙的用法。假设一个Map被用于带博鳌一个属性-值对的集合:putAll()方法与Map转化构造方法结合使用,提供另一种方法实现使用默认值的属性映射。下面使用这种技术的一个静态工厂方法的示例。

static<K,V>Map<K,V>newAttributeMap(Map<K,V>defaults,Map<K,V>overrides){
Map<K,V>result=new HashMap<K,V>(defaults);//创建一个新的Map对象
rusults.putAll(oerrides);
return result;
}

实现

实现时用于存储集合的数据对象实现了前面所说的一些接口。通俗来讲,实现是指这样一些类:这些类实现了各种集合框架的接口,在实际开发程序时,集合主要使用这些实现了集合接口的集合类。

实现类型

对于集合框架中集合接口的实现,主要包括如下几种类型。

通过目的的实现:是最经常使用的实现,是为日常使用而实现的。

特殊目的的实现:被设计用于特殊情况,并显示了非标准的执行特征、使用约束或行为。

并发实现:被设计用于高并发性,特别是单线程开销的情况下。这些实现时java.util.concurrent包的一部分。

其他实现:用于与其他特定目的的实现。

java集合框架提供了数个对Set、List和Map接口的通用实现。这些接口中每一个都有一个实现(TreeSet和TreeMap),在Set好人Map行列出。有两个通用的对Queue的实现:LinkedList(它同时也是List的实现)和PriorityQueue。这两个实现提供了不同的语义:Linked是FIFO的,而PriorityQueue根据元素的值排序。

每一个通用的目的的实现都提供了所有其接口中包含的操作:都允许null元素,键,值,且都不是同步的(线程安全的);都能在迭代其间检测非法的并发修改,且迅速失败并清除:都是可序列化的并且都支持公共的clone()方法。

事实上,这些实现都是非同步的,这与以前就版本的实现是不同的:遗留下来的集合Vector和Hashtable是同步的。之所以这样改变,是因为当集合被频繁地使用时,同步是无益的,这样的使用包括单线程使用,制度使用及作为大的数据对象的一部分使用(该大的数据对象有自己的同步)。一般来说,这是一个好的API设计的实践,用户不会为它们不使用的特征而付出额外的开销。进一步来讲,不必要的同步在一定的情况下会导致死锁。

如果需要线程安全的集合,可以使用同步包装的方法,允许任何集合被转换为一个同步的集合。此外,java.util.concurrent包提供BlockingQueue接口的同步实现,该接口扩展了Queue,以及对ConcurrentMap接口的实现,该接口扩展自Map。这些实现比同步实现提供更高的并发性。

作为一个原则,在使用集合时, 应该考虑的是接口,而不是实现。这就是为什么没有程序实例的原因。大多数情况下,对于实现的选择,只影响执行性能。当创建一个即可欧并立刻赋予一个新的集合给相对应的接口类型的变量时,选择实现(或者传递一个集合到一个需要接口类型参数的方法中)。以这种方式,程序并不依赖于一个给定实现当中的任何增加方法,这样,程序可以在任何时候因性能原因或行为细节而改变实现。。

Set接口的实现

Set接口不允许有重复的元素,因此Set接口的实现类要遵循这样的原则。Set实现分为通用实现和特殊实现。

1:通用Set实现

有3个通用的Set实现:HashSet,TreeSet,和LinkedHashSet。HashSet比TreeSet快,但是不提供顺序保证。如果需要使用SortedSet接口中的操作或要求按值的顺序迭代,则使用TreeSet;否则,使用HashSet。大多数情况下使用HashSet。

LinkedHashSet在某种意义上位于HashSet和TreeSet的中间。作为带有链表的哈希表,它提供插入顺序的迭代,运行速度接近于HashSet。LinkedHashSet实现避免了HashSet提供的混乱顺序,同时又没有想TreeSet那样增加高昂的成本。

更需要注意的是,HashSet在条目数量和容量数量上呈线状的迭代。因为初始容量选择太高会浪费时间和空间。另一方面,选择一个过低的容量会在强制增加一个容量时浪费复制数据结构的时间。如果不指定一个初始的容量,则默认是16.之前选择一个素数作为初始容量有一些好处,但是现在不是这样了。HashSet的容量总是以2 的几何级数增长,使用int构造方法指定初始容量。下面的代码,给定一个HashSet分配初始容量为64:

Set<String>s=new HashSet<String >(64);

HashSet类另一个调整的参数,称为“加载因子”。否则,仅接受默认值,默认值总是最好的选择。LinkedHashSet有和HashSet一样的调整因子,但是迭代时间不受容量的影响。TreeSet没有调整因子。

2:特殊目的的Set实现

有两个特殊目的的Set实现:EnumSet和CopyOnWriteArraySet。EnumSet是用于枚举类型的一个高性能的Set实现。一个枚举Set集合中的所有成员必须是相同的枚举类型。EnumSet支持在枚举类型上的范围迭代。例如,给定一个用于一周的天数的枚举声明,可以在周一至周五之前迭代。EnumSet类提供一个静态的工厂方法,代码如下:

for (Day d :EnumSet.range(Day.MONDAY,Day.FRIDAY))
System.out.println(d);

EnumSet还提供一个丰富的类型安全的对传统的位标志的替代。

EnumSet.of(Style.BOLD,Style.ITALIC)

CopyOnWriteArraySet是一个由拷贝数组支持的Set实现。所有的可变操作(如add()、set()和remove())通过对原数组的一次新的拷贝元素来实现:这个实现只适用于很少修改但经常迭代的Set集合。它适用于维护事件处理列表。

List接口的实现

对List接口的实现也是分为两类:通过目的的实现和特殊目的的实现。

1:通过目的的List实现

有两个通用目的的List实现:ArrayList和LinkedList。大多数时候,程序员或许都使用ArrayList。它不必为List中的每一个元素分配节点对象,并且它要在同一时刻移动多个元素时,可以使用System.arraycopy().将ArrayList当做不同步的向量Vector。

如果频繁地添加元素到List的开始位置或迭代List以从List的内部删除元素,应该考虑使用LinkedList。实际应用中,如果想使用LinkedList,在作出决定之前,先用LinkedList和ArrayList进行应用程序的性能测试:ArrayList通常快一点。

ArrayList有一个调整的参数----初始容量,它代表ArrayList在增长之前可以持有的元素的数量。LinkedList没有调整参数,有7个可选择的操作,其中一个是clone()。其他6个是addFirst(),getFirst(),removeFirst(),addLast(),getLast(),和removeLast()。LinkedList还实现了Queue接口。

2:特殊目的的List实现

CopyOnWriteArrayList是一个由拷贝数组支持的List实现。其本质上与CopyOnWriteArrayList相似。甚至在迭代其间,同步也是不是必须的,而且迭代保证永远不抛出ConcurrentM欧弟覅cationException。这个实现很适用于维护事件处理列表。在时间处理列表中很少发生改变,而遍历很频繁并且很耗时。

Map接口的实现

对Map接口的实现可分为三类:通用目的,特殊目的和并发实现。

1:通用目的的Map实现

3个通用目的的Map实现分别是HashMap,TreeMap和LinkedHashMap。

如果需要SortedMap操作,或者按键顺序的视图迭代,使用TreeMap。

如果想要最大的速度而不关心迭代的顺序,使用HashMap。

如果想要接近HashSet性能和按插入顺序迭代,使用LinkedHashMap。

在这方面,Map情形与Set类似同样在“Set实现”中的任何事情都可应用有Map实现。

LinkedHashMap提供两个LinkedHashSet不具备的性能。当创建一个LinkedHashMap时,可以基于键的访问顺序来排序,而不是基于插入顺序。换句话来说,仅查找与一个键关联的值引起该键到Map的结尾,另外,LinkedHashMap提供removeEldestEntry()方法,该方法可以被覆盖以强加一个策略,该策略用于当新的映射被添加到Map中时,自动地删除过时的映射。这使得实现一个自定义缓冲非常容易。

例如下面的代码覆盖将允许Map增长到90条目的大小,然后每次一个新的条目被加入时,Map将删除最老的那个条目,维护90个条目的稳定状态。

private static final int MAX_ENTRIES=90;

protected boolean removeEldestEntry(Map.Entry eldest){
return size() >MAX_ENTRIES;
}

2:特殊目的的Map实现

有3个特殊目的的Map实现:EnumMap,WeakHashMap,IdentityHashMap.

3:并发的Map实现

java.util.conrrent包中含有ConcurrentMap接口,它扩展自Map,带有putIfAbsent(),remove(),replace()方法,以及该接口ConcurrentHashMap实现。

时间: 2024-10-12 16:41:22

集合2的相关文章

数组、字符串、集合

数组与集合的转换.数组与字符串的转换 ========数组变集合 String[] arr = {"abc","cc","kkkk"}; //把数组变成list集合有什么好处? /* 可以使用集合的思想和方法来操作数组中的元素. 注意:将数组变成集合,不可以使用集合的增删方法. 因为数组的长度是固定. contains. get indexOf() subList(); 如果你增删.那么会产生UnsupportedOperationExcepti

C#语言中数组和集合

数组.集合→用于储存多个同类型的数据数组 定长→用于保存固定数量的数据 在功能上,数组能实现的所有功能,集合都能实现:反之,集合能实现的某些功能,数组难以实现 占用内存少 便利速度快集合 不定长→保存的数据数量,可以在程序的执行过程中,发生变化 占用内存多 便利速度慢课时六:数组和集合 数组.集合→用于储存多个同类型的数据 数组 定长→用于保存固定数量的数据 在功能上,数组能实现的所有功能,集合都能实现:反之,集合能实现的某些功能,数组难以实现 占用内存少 便利速度快 集合 不定长→保存的数据数

通过反射了解集合泛型的本质

通过反射了解集合泛型的本质 import java.lang.reflect.Method; import java.util.ArrayList; /** * 通过反射了解集合泛型的本质 * @author shm * */ public class MethodDemo02 { public static void main(String[] args) { ArrayList list = new ArrayList(); list.add("hello"); list.add(

Java 之集合

collection(单列集合) List(有序,可重复) ArrayList     底层数据结构是数组,查询快,增删慢,线程不安全,效率高 Vector     底层数据结构是数组,查询快,增删慢,线程安全,效率低 LinkedList  底层数据结构是链表,查询慢,增删快,线程不安全,效率高 Set(无序,唯一) HashSet   底层数据结构是哈希表,依赖hashCode()和equals() 执行顺序:判断hashCode()是否相同,相同继续执行equals(),返回true不添加

集合和三元运算符

一.三元运算符 如下判断可以使用三元运算更方便的实现: a = 1b = 2 if a > 1: c = aelse: c = b 和下面是一样的: a = 1b = 2#下面这个c = a if a>1 else b 如下两种方法也是一样的:方式一: s=[]nums = list(range(1,11))for i in nums: if i%2==0: s.append(i)print(s)方式二:ss = [i for i in nums if i%2==0]print(ss)#这两种

集合函数 day4

1.集合 通过set强制转换,或者直接定义 1 nums = [0, 2, 4, 6, 8]#两种格式,带大括号与带中括号的 2 print(type(nums)) 3 aa = {0, 8, 2, 4, 6}#需要注意与字典的区别,字典是有分号的 2.交集

js算法集合(一) 水仙花数 及拓展(自幂数的判断)

js算法集合(一) ★ 最近有些朋友跟我说对js中的一些算法感到很迷惑,知道这个算法到底是怎么回事,但是就是不会用代码把它写出来,这里我跟大家分享一下做水仙花数的算法的思路,并对其扩展到自幂数的算法,希望能对大家有所帮助. 1.验证一个数是否为水仙花数 ①要写水仙花数的算法,我们首先来了解一下什么是水仙花数,水仙花数是指一个 3位正整数 ,它的每个位上的数字的 3次幂之和等于它本身.(例如:1^3 + 5^3+ 3^3 = 153): ②了解了什么是水仙花数我们就开始分析该怎么下手.通过定义来看

笔记:多线程-集合

阻塞队列(BlockingQueue) 当试图向队列添加元素而队列已满,或是想从队列移除元素而队列为空的时候,阻塞队列导致线程阻塞,阻塞队列接口定义如下,他继承Queue<E>接口: public interface BlockingQueue<E> extends Queue<E> { ????/** ???? * 添加一个元素,如果队列满,则抛出 IllegalStateException异常 ???? */ ????????boolean add(E e); ??

SQL入门之集合操作

尽管可以在与数据库交互时一次只处理一行数据,但实际上关系数据库通常处理的都是数据的集合.在数学上常用的集合操作为:并(union),交(intersect),差(except).对于集合运算必须满足下面两个要求: 两个数据集合必须具有同样数目的列 连个数据集中对应列的数据类型必须是一样的(或者服务器能够将其中一种类型转换为另一种类型) SQL语言中每个集合操作符包含两种修饰:一个包含重复项,另一个去除了重复项(但不一定去除了所有重复项). 0.union操作符 union和union all操作

Java—集合框架List

集合的概念 现实生活中:很多的事物凑在一起 数学中的集合:具有共同属性的事物的总和 Java中的集合类:是一种工具类,就像是容器,存储任意数量的具有共同属性的对象 集合的作用 在类的内部,对数据进行组织(针对作用与意义一样的属性,将他们放到一个集合中) 简单而快速的搜索大数量的条目 有的集合接口,提供了一系列排列有序的元素,并且可以在序列中快速的插入或删除有关元素 有的集合接口,提供了映射关系,可以通过关键字(key)去快速查找到对应的唯一对象,而这个关键字可以是任意类型 与数组相比 数组的长度