1.数组声明
int score[] = new int[]{1,2,3}; int[] score2 = {1,2,3}; int[] score3 = new int[3];
2.集合
先上一张逻辑图。
在JAVA中,集合容器分为两类:一种是单值的Collection,一种是存储键-值对的Map。
- Colleciton:Collection是一个接口,用于表示任何对象或元素组。
- Collection接口的方法(Collection不提供get方法,要遍历Collection必须使用Iterator)。
-
- 单元素添加、删除操作:boolean add(Object o);boolean remove(Objcet o);
- 查询操作:int size();boolean isEmpty();boolean contains(Object o);Iterator iterator()//返回一个迭代器,用于访问集合各元素;
- 组操作:boolean containsAll(Collection c);boolean addAll(Collection c);void clear();void removeAll(Collection c);void retainAll(Collection c)//从集合中删除集合c中不包含的元素,即取与集合c的交集;
- 转Objcet数组操作:Object[] toArray()//返回一个包含集合内所有元素的array(必须是Object对象,不能是基本数据类型);Object[] toArray(Object[] a)//返回一个包含集合内所有元素的array,其中a表示存储此 collection 元素的数组(如果其足够大),否则,将为此分配一个具有相同运行时类型的新数组;
- AbstarctCollection抽象类:该类是Collection接口的抽象实现类,它提供了具体“集合框架”的基本功能,该类提供了除 iterator()和size()外其他方法的实现,不过AbstarctCollection类对于add()方法(该方法在 AbstarctCollection中的实现是直接抛出UnsupportedOperationException异常),在使用时需要重新实现。
- Iterator接口:Collection通过iterator()方法返回一个Iterator(迭代器)。该接口以迭代的方式逐个访问集合中的各个元素,并安全地从Collection中除去适当的元素。
- 注意:这里的“安全”是指(网上解释):Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭 代的对象,所以按照 fail-fast 原则(故障快速修复) Iterator 会马上抛出java.util.ConcurrentModificationException 异常。所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。看以下代码:
public static void main(String[] args) { Set<String> set = new HashSet<String>(); set.add("a"); set.add("b"); set.add("c"); set.add("d"); Iterator<String> iterator = set.iterator(); /* 下面这个while循环中进行删除就是正常的*/ while (iterator.hasNext()) { String string = (String) iterator.next(); if (string.endsWith("c")) { iterator.remove(); } } /* 下面这个for循环中进行删除就会抛异常*/ /*for (String string : set) { if (string.endsWith("c")) { set.remove(string); } }*/ for (String string : set) { System.out.println(string); } }
- 注意:这里的“安全”是指(网上解释):Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭 代的对象,所以按照 fail-fast 原则(故障快速修复) Iterator 会马上抛出java.util.ConcurrentModificationException 异常。所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。看以下代码:
-
- ListIterator接口:它集成自Iterator接口,以支持添加或更改底层集合中的元素,还支持双向访问,它没有当前位置,光标位于previous和next方法返回的值之间。
- 关于ListIterator的几个方法:
- Object previous():返回光标前一个对象,并且光标前移一位。
- Object next():返回光标后一个对象,并且光标后移一位。由于光标处于两者之间,所以连续调用next和previous方法返回是同一个对象。
- void add(Object o):添加一个元素,添加的位置是当前光标的前面,所以在用add添加一个元素后,调用previous()方法会返回刚刚添加的元素,而next方法的返回值不受add方法影响。
- void set(Object o):对一个元素进行设值,这个元素是前一次调用previous()或next()方法后返回的那个元素。(注:如果上次调用后列表结构被修改了,那么将抛出IllegalStateException 异常。)
public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("a"); list.add("b"); list.add("c"); ListIterator<String> listIterator = list.listIterator(); if (listIterator.hasNext()) { System.out.println(listIterator.nextIndex()); System.out.println(listIterator.next()); System.out.println(listIterator.nextIndex()); System.out.println(listIterator.previous()); System.out.println(listIterator.nextIndex()); System.out.println("----------------------"); System.out.println(listIterator.next()); listIterator.set("m"); System.out.println(listIterator.previous()); listIterator.add("n"); System.out.println(listIterator.previous()); } } //输出结果为: 0 a 1 a 0 ---------------------- a m n
- 关于ListIterator的几个方法:
- AbstractList和AbstractSequentialList抽象类:都是List的抽象实现类,它们覆盖了equals()和hashCode()方法,确保相等集合返回相同的哈希码。此外,AbstractList和AbstractSequentialList实现了List的其余一些方法,其中包括iterator方法的实现。
- RandomAccess接口:这是一个特征接口,当某个集合实现类实现该接口的时候,表示该集合实现类支持有效的随机访问。ArrayList和Vector类都实现了该接口。
- 注意:JDK中推荐对于List集合尽量要实现RandomAccess接口,如果集合实现了该接口,那么在遍历该集合的时候,尽量使用for(int i = 0; i < size; i++)来遍历,而不要使用Iterator迭代器来实现。反之,如果List是Sequence List,则最好采用迭代器来迭代。JDK中说的很清楚,在对List特别是Huge size的List的遍历算法中,要尽量来判断是属于RandomAccess(如ArrayList)还是Sequence List (如LinkedList),因为适合RandomAccess List的遍历算法,用在Sequence List上就差别很大,常用的作法就是:
if (list instanceof RandomAccess) { for(int m = 0; m < list.size(); m++){ } }else{ Iterator iter = list.iterator(); while(iter.hasNext()){ } }
- 注意:JDK中推荐对于List集合尽量要实现RandomAccess接口,如果集合实现了该接口,那么在遍历该集合的时候,尽量使用for(int i = 0; i < size; i++)来遍历,而不要使用Iterator迭代器来实现。反之,如果List是Sequence List,则最好采用迭代器来迭代。JDK中说的很清楚,在对List特别是Huge size的List的遍历算法中,要尽量来判断是属于RandomAccess(如ArrayList)还是Sequence List (如LinkedList),因为适合RandomAccess List的遍历算法,用在Sequence List上就差别很大,常用的作法就是:
- Comparable接口和Comparator接口:集合框架中的两种比较接口。
- 实现了Comparable接口的JAVA类需要实现compareTo(Object o)方法,用于比较当前对象与对象o的顺序,如果位于对象o之前,就返回负数,如果两个对象位置相同,则返回0(注意:0只是表示位置相同,元素不一定相同),如果在o之后,则返回正值。
- 如果一个类无法或不方便实现Comparable接口,并且向提供自己的排序方式,可以自行实现Comparator接口,从而定义一个比较器,比较器包含compare(Object o1, Object2)和equalse(Object o)两个方法,第一个方法用于比较o1和o2两个对象顺序,如果o1在o2前面,则返回负值,如果相等则返回0(注意:0只是表示位置相同,元素不一定相同),如果o1位于o2后面,则返回正值。第二个equalse方法用于比较对象o是否与比较器相等。
- SortedSet接口:特殊的集合接口,它保持元素的有序排序(从低到高)。注意:这里的有序,不是指元素的录入顺序,而是指元素在加入该类集合后,会根据comparable接口实现的compareTo方法或Comparator接口的comapre方法进行比较,按返回结果对元素进行有序排列。具体可见下面代码:
public static void main(String[] args) { Set<String> ts = new TreeSet<String>(); ts.add("c"); ts.add("z"); ts.add("a"); ts.add("b"); ts.add("3"); for (String string : ts) { System.out.println(string); } } //输出结果为: 3 a b c z
由于需要对元素排序,所以添加到SortedSet的元素必须实现Comparable接口,否则必须为SortedSet接口实现类的构造方法提供一个Comparator接口的实现。例如SortedSet接口的唯一实现类TreeSet,它就提供了一个包含Comparator接口的构造方法:
public TreeSet(Comparator<? super E> comparator) { this(new TreeMap<E,Object>(comparator)); }
该接口提供了访问集合的视图(子集)和两端的方法。
- Comparator comparator():返回对元素进行排序时的比较器,如果使用Comparable接口的compareTo方法进行比较,则返回null
- Object first():返回有序集合中的第一个(最低)元素。
- Object last():返回有序集合中的最后(最高)一个元素。
- SortedSet subSet(Object fromElement, Object endElement):返回从fromElement(包括)到endElement(不包括)范围内元素的SortedSet视图(子集)
- SortedSet headSet(Object toElement):返回一个视图(子集),包括集合中所有小于toElement的元素。
- SortedSet tailSet(Object fromElement):返回一个视图(子集),包括集合中所有大于或等于fromElement的元素。
- AbstractSet抽象类:该类覆盖了equals和hashCode方法。
- ListIterator接口:它集成自Iterator接口,以支持添加或更改底层集合中的元素,还支持双向访问,它没有当前位置,光标位于previous和next方法返回的值之间。
- Map接口:Map接口用于维护键/值对,该接口描述了从不重复的键到值的映射。
- Map接口的方法:
-
- 添加删除操作:Object put(Object key, Object value)//如果key已存在,则覆盖旧值,并返回旧值,如果不存在则添加并返回null;Object remove(Object key);void putAll(Map t);void clear();(注意:map的key和value都可以是null)
public static void main(String[] args) { Map<String, String> map1 = new HashMap<String, String>(); map1.put("a", "a"); Map<String, Map> map = new HashMap<String, Map>(); map.put("0", map1); map.put("1", map); Map neeMap = map.get("1"); System.out.println(neeMap == map); System.out.println(neeMap.get("0")); }
返回结果是:true和{a=a}
说明:Map可以把自身作为key或value添加给自身。 - 查询操作:Object get(Object key)//如果找不到则返回null;boolean containsKey(Object key);boolean containsValue(Object value);int size();boolean isEmpty();
- 视图操作:Set keySet()//返回所有key的视图集;Collection values()//返回所有value的视图集;Set entrySet()//返回Map.Entry对象的视图集;(注意:开发者可以将所有返回的视图集中的元素删除,同时它对应的源中的key/value也会被删除,但是不能在视图集中添加元素)
public static void main(String[] args) { Map<String, String> map = new HashMap<String, String>(); map.put("a", "1"); map.put("b", "2"); map.put("c", "3"); Set<Entry<String, String>> set = map.entrySet(); Iterator<Entry<String, String>> iterator = set.iterator(); while (iterator.hasNext()) { Entry<String, String> entry = iterator.next(); if (entry.getKey().equals("b")) { iterator.remove(); } } for (Entry<String, String> entry : set) { System.out.println("修改前key为:" + entry.getKey() + " value为:" + entry.getValue()); entry.setValue(entry.getValue() + "~~"); System.out.println("修改后key为:" + entry.getKey() + " value为:" + entry.getValue()); } } //输出结果为: 修改前key为:c value为:3 修改后key为:c value为:3~~ 修改前key为:a value为:1 修改后key为:a value为:1~~
- 添加删除操作:Object put(Object key, Object value)//如果key已存在,则覆盖旧值,并返回旧值,如果不存在则添加并返回null;Object remove(Object key);void putAll(Map t);void clear();(注意:map的key和value都可以是null)
- Map.Entry接口:Map的entrySet()方法返回一个实现了Map.Entry接口的对象集合,通过这个集合的迭代器,您可以获得每一个条目(唯一获取方式)的键或值并对值进行更改。当条目通过迭代器返回后,除非是迭代器自身的remove()方 法或者迭代器返回的条目的setValue()方法,其余对源Map外部的修改都会导致此条目集变得无效,同时产生条目行为未定义。
- SortedMap接口:SortedMap接口是集成自Map的一个特殊接口,它用来保持键的有序顺序。处理与SorterSet一样,只是它比较的是Map的key。
- AbstractMap抽象类:与AbstractSet、AbstractList类似,覆盖了equals和hashCode方法。
- WeakHashMap类:WeakHashMap是Map的一个特殊实现,它使用WeakReference(弱引用)来存放哈希表关键字。使用这种方式时,当映射的键在 WeakHashMap 的外部不再被引用时,垃圾收集器会将它回收,但它将把到达该对象的弱引用纳入一个队列。WeakHashMap的运行将定期检查该队列,以便找出新到达的 弱应用。当一个弱引用到达该队列时,就表示关键字不再被任何人使用,并且它已经被收集起来。然后WeakHashMap便删除相关的映射。
- (1) WeakHashMap(): 构建一个空弱哈希映像
- (2) WeakHashMap(Map t): 构建一个弱哈希映像,并且添加映像t中所有映射
- (3) WeakHashMap(int initialCapacity): 构建一个拥有特定容量的空的弱哈希映像
- (4) WeakHashMap(int initialCapacity, float loadFactor): 构建一个拥有特定容量和加载因子的空的弱哈希映像
- IdentityHashMap类:IdentityHashMap也是Map的一个特殊实现。在这个类中,关键字的哈希码不应该由hashCode()方法来计算,而应该由 System.identityHashCode方法进行计算(即使已经重新定义了hashCode方法)。这是Object.hashCode根据对象的内存地址来计算哈希码时使用的方法。另外,为了对各个对象进行比较,IdentityHashMap将使用==,而不使用equals方法。换句话说,不同的关键字对象,即使它们的内容相同,也被视为不同的对象。IdentityHashMap类可以用于实现对象拓扑结构转换 (topology-preserving object graph transformations)(比如实现对象的串行化或深度拷贝),在进行转换时,需要一个“节点表”跟踪那些已经处理过的对象的引用。即使碰巧有对象相等,“节点表”也不应视其相等。另一个应用是维护代理对象。比如,调试工具希望在程序调试期间维护每个对象的一个代理对象。
IdentityHashMap类不是一般意义的Map实现,它的实现有意的违背了Map接口要求通过equals方法比较对象的约定。这个类仅使用在很少发生的需要强调等同性语义的情况。
(1) IdentityHashMap (): 构建一个空的全同哈希映像,默认预期最大尺寸为21
“预期最大尺寸是映像期望把持的键/值映射的最大数目”
(2) IdentityHashMap (Map m): 构建一个全同哈希映像,并且添加映像m中所有映射
(3) IdentityHashMap (int expectedMaxSize): 构建一个拥有预期最大尺寸的空的全同哈希映像。放置超过预期最大尺寸的键/值映射时,将引起内部数据结构的增长,有时可能很费时 。
时间: 2024-10-18 08:12:43