// onjava/HTMLColors.java// Sample data for collection examplespackageonjava;importjava.util.*;importjava.util.stream.*;importjava.util.concurrent.*;publicclassHTMLColors{publicstaticfinalObject[][] ARRAY ={{0xF0F8FF,"AliceBlue"},{0xFAEBD7,"AntiqueWhite"},{0x7FFFD4,"Aquamarine"},{0xF0FFFF,"Azure"},{0xF5F5DC,"Beige"},{0xFFE4C4,"Bisque"},{0x000000,"Black"},{0xFFEBCD,"BlanchedAlmond"},{0x0000FF,"Blue"},{0x8A2BE2,"BlueViolet"},{0xA52A2A,"Brown"},{0xDEB887,"BurlyWood"},{0x5F9EA0,"CadetBlue"},{0x7FFF00,"Chartreuse"},{0xD2691E,"Chocolate"},{0xFF7F50,"Coral"},{0x6495ED,"CornflowerBlue"},{0xFFF8DC,"Cornsilk"},{0xDC143C,"Crimson"},{0x00FFFF,"Cyan"},{0x00008B,"DarkBlue"},{0x008B8B,"DarkCyan"},{0xB8860B,"DarkGoldenRod"},{0xA9A9A9,"DarkGray"},{0x006400,"DarkGreen"},{0xBDB76B,"DarkKhaki"},{0x8B008B,"DarkMagenta"},{0x556B2F,"DarkOliveGreen"},{0xFF8C00,"DarkOrange"},{0x9932CC,"DarkOrchid"},{0x8B0000,"DarkRed"},{0xE9967A,"DarkSalmon"},{0x8FBC8F,"DarkSeaGreen"},{0x483D8B,"DarkSlateBlue"},{0x2F4F4F,"DarkSlateGray"},{0x00CED1,"DarkTurquoise"},{0x9400D3,"DarkViolet"},{0xFF1493,"DeepPink"},{0x00BFFF,"DeepSkyBlue"},{0x696969,"DimGray"},{0x1E90FF,"DodgerBlue"},{0xB22222,"FireBrick"},{0xFFFAF0,"FloralWhite"},{0x228B22,"ForestGreen"},{0xDCDCDC,"Gainsboro"},{0xF8F8FF,"GhostWhite"},{0xFFD700,"Gold"},{0xDAA520,"GoldenRod"},{0x808080,"Gray"},{0x008000,"Green"},{0xADFF2F,"GreenYellow"},{0xF0FFF0,"HoneyDew"},{0xFF69B4,"HotPink"},{0xCD5C5C,"IndianRed"},{0x4B0082,"Indigo"},{0xFFFFF0,"Ivory"},{0xF0E68C,"Khaki"},{0xE6E6FA,"Lavender"},{0xFFF0F5,"LavenderBlush"},{0x7CFC00,"LawnGreen"},{0xFFFACD,"LemonChiffon"},{0xADD8E6,"LightBlue"},{0xF08080,"LightCoral"},{0xE0FFFF,"LightCyan"},{0xFAFAD2,"LightGoldenRodYellow"},{0xD3D3D3,"LightGray"},{0x90EE90,"LightGreen"},{0xFFB6C1,"LightPink"},{0xFFA07A,"LightSalmon"},{0x20B2AA,"LightSeaGreen"},{0x87CEFA,"LightSkyBlue"},{0x778899,"LightSlateGray"},{0xB0C4DE,"LightSteelBlue"},{0xFFFFE0,"LightYellow"},{0x00FF00,"Lime"},{0x32CD32,"LimeGreen"},{0xFAF0E6,"Linen"},{0xFF00FF,"Magenta"},{0x800000,"Maroon"},{0x66CDAA,"MediumAquaMarine"},{0x0000CD,"MediumBlue"},{0xBA55D3,"MediumOrchid"},{0x9370DB,"MediumPurple"},{0x3CB371,"MediumSeaGreen"},{0x7B68EE,"MediumSlateBlue"},{0x00FA9A,"MediumSpringGreen"},{0x48D1CC,"MediumTurquoise"},{0xC71585,"MediumVioletRed"},{0x191970,"MidnightBlue"},{0xF5FFFA,"MintCream"},{0xFFE4E1,"MistyRose"},{0xFFE4B5,"Moccasin"},{0xFFDEAD,"NavajoWhite"},{0x000080,"Navy"},{0xFDF5E6,"OldLace"},{0x808000,"Olive"},{0x6B8E23,"OliveDrab"},{0xFFA500,"Orange"},{0xFF4500,"OrangeRed"},{0xDA70D6,"Orchid"},{0xEEE8AA,"PaleGoldenRod"},{0x98FB98,"PaleGreen"},{0xAFEEEE,"PaleTurquoise"},{0xDB7093,"PaleVioletRed"},{0xFFEFD5,"PapayaWhip"},{0xFFDAB9,"PeachPuff"},{0xCD853F,"Peru"},{0xFFC0CB,"Pink"},{0xDDA0DD,"Plum"},{0xB0E0E6,"PowderBlue"},{0x800080,"Purple"},{0xFF0000,"Red"},{0xBC8F8F,"RosyBrown"},{0x4169E1,"RoyalBlue"},{0x8B4513,"SaddleBrown"},{0xFA8072,"Salmon"},{0xF4A460,"SandyBrown"},{0x2E8B57,"SeaGreen"},{0xFFF5EE,"SeaShell"},{0xA0522D,"Sienna"},{0xC0C0C0,"Silver"},{0x87CEEB,"SkyBlue"},{0x6A5ACD,"SlateBlue"},{0x708090,"SlateGray"},{0xFFFAFA,"Snow"},{0x00FF7F,"SpringGreen"},{0x4682B4,"SteelBlue"},{0xD2B48C,"Tan"},{0x008080,"Teal"},{0xD8BFD8,"Thistle"},{0xFF6347,"Tomato"},{0x40E0D0,"Turquoise"},{0xEE82EE,"Violet"},{0xF5DEB3,"Wheat"},{0xFFFFFF,"White"},{0xF5F5F5,"WhiteSmoke"},{0xFFFF00,"Yellow"},{0x9ACD32,"YellowGreen"},};publicstaticfinalMap<Integer,String> MAP =Arrays.stream(ARRAY).collect(Collectors.toMap( element ->(Integer)element[0], element ->(String)element[1],(v1, v2)->{// Merge functionthrownew IllegalStateException();}, LinkedHashMap::new)); // Inversion only works if values are unique:publicstatic<V,K>Map<V,K>invert(Map<K,V>map){returnmap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue,Map.Entry::getKey,(v1, v2)->{thrownew IllegalStateException();}, LinkedHashMap::new));}publicstaticfinalMap<String,Integer> INVMAP =invert(MAP); // Look up RGB value given a name:publicstaticIntegerrgb(StringcolorName){returnINVMAP.get(colorName);}publicstaticfinalList<String> LIST =Arrays.stream(ARRAY).map(item ->(String)item[1]).collect(Collectors.toList());publicstaticfinalList<Integer> RGBLIST =Arrays.stream(ARRAY).map(item ->(Integer)item[0]).collect(Collectors.toList());publicstaticvoidshow(Map.Entry<Integer,String>e){System.out.format("0x%06X: %s%n",e.getKey(),e.getValue());}publicstaticvoidshow(Map<Integer,String>m,intcount){m.entrySet().stream().limit(count).forEach(e -> show(e));}publicstaticvoidshow(Map<Integer,String>m){show(m,m.size());}publicstaticvoidshow(Collection<String>lst,intcount){lst.stream().limit(count).forEach(System.out::println);}publicstaticvoidshow(Collection<String>lst){show(lst,lst.size());}publicstaticvoidshowrgb(Collection<Integer>lst,intcount){lst.stream().limit(count).forEach(n ->System.out.format("0x%06X%n", n));}publicstaticvoidshowrgb(Collection<Integer>lst){showrgb(lst,lst.size());}publicstaticvoidshowInv(Map<String,Integer>m,intcount){m.entrySet().stream().limit(count).forEach(e ->System.out.format("%-20s 0x%06X%n",e.getKey(),e.getValue()));}publicstaticvoidshowInv(Map<String,Integer>m){showInv(m,m.size());}publicstaticvoidborder(){System.out.println("******************************");}}
下面是一个可以是任何大小的 List ,并且(有效地)使用 Integer 数据进行预初始化。要从 AbstractList 创建只读 List ,必须实现 get() 和 size():
只有当想要限制 List 的长度时, size 值才是重要的,就像在主方法中那样。即使在这种情况下, get() 也会产生任何值。
这个类是享元模式的一个简洁的例子。当需要的时候, get() “计算”所需的值,因此没必要存储和初始化实际的底层 List 结构。
在大多数程序中,这里所保存的存储结构永远都不会改变。但是,它允许用非常大的 index 来调用 List.get() ,而 List 并不需要填充到这么大。此外,还可以在程序中大量使用 CountingIntegerLists 而无需担心存储问题。实际上,享元的一个好处是它允许使用更好的抽象而不用担心资源。
test() 中的最后一个 check() 用于测试List 的 set() 方法。这里,“不支持的操作”技术的粒度(granularity)就派上用场了,得到的“接口”可以通过一种方法在 Arrays.asList() 返回的对象和 Collections.unmodifiableList() 返回的对象之间变换。 Arrays.asList() 返回固定大小的 List ,而 Collections.unmodifiableList() 生成无法更改的 List 。如输出中所示, Arrays.asList() 返回的 List 中的元素是可以修改的,因为这不会违反该 List 的“固定大小”特性。但很明显, unmodifiableList() 的结果不应该以任何方式修改。如果使用接口来描述,则需要两个额外的接口,一个具有可用的 set() 方法,而另一个没有。 Collection 的各种不可修改的子类型都将需要额外的接口。
如果一个方法将一个集合作为它的参数,那么它的文档应该说明必须实现哪些可选方法。
Set和存储顺序
第十二章 集合章节中的 Set 有关示例对 Set 的基本操作做了很好的介绍。 但是,这些示例可以方便地使用预定义的 Java 类型,例如 Integer 和 String ,它们可以在集合中使用。在创建自己的类型时请注意, Set (以及稍后会看到的 Map )需要一种维护存储顺序的方法,该顺序因 Set 的不同实现而异。因此,不同的 Set 实现不仅具有不同的行为,而且它们对可以放入特定 Set 中的对象类型也有不同的要求:
Set 类型
约束
Set(interface)
添加到 Set 中的每个元素必须是唯一的,否则,Set 不会添加重复元素。添加到 Set 的元素必须至少定义 equals() 方法以建立对象唯一性。 Set 与 Collection 具有完全相同的接口。 Set 接口不保证它将以任何特定顺序维护其元素。
HashSet*
注重快速查找元素的集合,其中元素必须定义 hashCode() 和 equals() 方法。
TreeSet
由树支持的有序 Set。这样,就可以从 Set 中获取有序序列,其中元素必须实现 Comparable 接口。
LinkedHashSet
具有 HashSet 的查找速度,但在内部使用链表维护元素的插入顺序。因此,当在遍历 Set 时,结果将按元素的插入顺序显示。元素必须定义 hashCode() 和 equals() 方法。
在 TypesForSets 中, fill() 和 test() 都是使用泛型定义的,以防止代码重复。为了验证 Set 的行为, test() 在测试集上调用 fill() 三次,尝试引入重复的对象。 fill() 方法的参数可以接收任意一个 Set 类型,以及生成该类型的 Function 对象。因为此示例中使用的所有对象都有一个带有单个 int 参数的构造方法,所以可以将构造方法作为此 Function 传递,它将提供用于填充 Set 的对象。
// collectiontopics/ListOps.java
// Things you can do with Lists
import java.util.*;
import onjava.HTMLColors;
public class ListOps {
// Create a short list for testing:
static final List<String> LIST =
HTMLColors.LIST.subList(0, 10);
private static boolean b;
private static String s;
private static int i;
private static Iterator<String> it;
private static ListIterator<String> lit;
public static void basicTest(List<String> a) {
a.add(1, "x"); // Add at location 1
a.add("x"); // Add at end
// Add a collection:
a.addAll(LIST);
// Add a collection starting at location 3:
a.addAll(3, LIST);
b = a.contains("1"); // Is it in there?
// Is the entire collection in there?
b = a.containsAll(LIST);
// Lists allow random access, which is cheap
// for ArrayList, expensive for LinkedList:
s = a.get(1); // Get (typed) object at location 1
i = a.indexOf("1"); // Tell index of object
b = a.isEmpty(); // Any elements inside?
it = a.iterator(); // Ordinary Iterator
lit = a.listIterator(); // ListIterator
lit = a.listIterator(3); // Start at location 3
i = a.lastIndexOf("1"); // Last match
a.remove(1); // Remove location 1
a.remove("3"); // Remove this object
a.set(1, "y"); // Set location 1 to "y"
// Keep everything that's in the argument
// (the intersection of the two sets):
a.retainAll(LIST);
// Remove everything that's in the argument:
a.removeAll(LIST);
i = a.size(); // How big is it?
a.clear(); // Remove all elements
}
public static void iterMotion(List<String> a) {
ListIterator<String> it = a.listIterator();
b = it.hasNext();
b = it.hasPrevious();
s = it.next();
i = it.nextIndex();
s = it.previous();
i = it.previousIndex();
}
public static void iterManipulation(List<String> a) {
ListIterator<String> it = a.listIterator();
it.add("47");
// Must move to an element after add():
it.next();
// Remove the element after the new one:
it.remove();
// Must move to an element after remove():
it.next();
// Change the element after the deleted one:
it.set("47");
}
public static void testVisual(List<String> a) {
System.out.println(a);
List<String> b = LIST;
System.out.println("b = " + b);
a.addAll(b);
a.addAll(b);
System.out.println(a);
// Insert, remove, and replace elements
// using a ListIterator:
ListIterator<String> x =
a.listIterator(a.size()/2);
x.add("one");
System.out.println(a);
System.out.println(x.next());
x.remove();
System.out.println(x.next());
x.set("47");
System.out.println(a);
// Traverse the list backwards:
x = a.listIterator(a.size());
while(x.hasPrevious())
System.out.print(x.previous() + " ");
System.out.println();
System.out.println("testVisual finished");
}
// There are some things that only LinkedLists can do:
public static void testLinkedList() {
LinkedList<String> ll = new LinkedList<>();
ll.addAll(LIST);
System.out.println(ll);
// Treat it like a stack, pushing:
ll.addFirst("one");
ll.addFirst("two");
System.out.println(ll);
// Like "peeking" at the top of a stack:
System.out.println(ll.getFirst());
// Like popping a stack:
System.out.println(ll.removeFirst());
System.out.println(ll.removeFirst());
// Treat it like a queue, pulling elements
// off the tail end:
System.out.println(ll.removeLast());
System.out.println(ll);
}
public static void main(String[] args) {
// Make and fill a new list each time:
basicTest(new LinkedList<>(LIST));
basicTest(new ArrayList<>(LIST));
iterMotion(new LinkedList<>(LIST));
iterMotion(new ArrayList<>(LIST));
iterManipulation(new LinkedList<>(LIST));
iterManipulation(new ArrayList<>(LIST));
testVisual(new LinkedList<>(LIST));
testLinkedList();
}
}
/* Output:
[AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige,
Bisque, Black, BlanchedAlmond, Blue, BlueViolet]
b = [AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige,
Bisque, Black, BlanchedAlmond, Blue, BlueViolet]
[AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige,
Bisque, Black, BlanchedAlmond, Blue, BlueViolet,
AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige,
Bisque, Black, BlanchedAlmond, Blue, BlueViolet,
AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige,
Bisque, Black, BlanchedAlmond, Blue, BlueViolet]
[AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige,
Bisque, Black, BlanchedAlmond, Blue, BlueViolet,
AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, one,
Bisque, Black, BlanchedAlmond, Blue, BlueViolet,
AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige,
Bisque, Black, BlanchedAlmond, Blue, BlueViolet]
Bisque
Black
[AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige,
Bisque, Black, BlanchedAlmond, Blue, BlueViolet,
AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, one,
47, BlanchedAlmond, Blue, BlueViolet, AliceBlue,
AntiqueWhite, Aquamarine, Azure, Beige, Bisque, Black,
BlanchedAlmond, Blue, BlueViolet]
BlueViolet Blue BlanchedAlmond Black Bisque Beige Azure
Aquamarine AntiqueWhite AliceBlue BlueViolet Blue
BlanchedAlmond 47 one Beige Azure Aquamarine
AntiqueWhite AliceBlue BlueViolet Blue BlanchedAlmond
Black Bisque Beige Azure Aquamarine AntiqueWhite
AliceBlue
testVisual finished
[AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige,
Bisque, Black, BlanchedAlmond, Blue, BlueViolet]
[two, one, AliceBlue, AntiqueWhite, Aquamarine, Azure,
Beige, Bisque, Black, BlanchedAlmond, Blue, BlueViolet]
two
two
one
BlueViolet
[AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige,
Bisque, Black, BlanchedAlmond, Blue]
*/
// collectiontopics/NavMap.java
// NavigableMap produces pieces of a Map
import java.util.*;
import java.util.concurrent.*;
import static onjava.HTMLColors.*;
public class NavMap {
public static final
NavigableMap<Integer,String> COLORS =
new ConcurrentSkipListMap<>(MAP);
public static void main(String[] args) {
show(COLORS.firstEntry());
border();
show(COLORS.lastEntry());
border();
NavigableMap<Integer, String> toLime =
COLORS.headMap(rgb("Lime"), true);
show(toLime);
border();
show(COLORS.ceilingEntry(rgb("DeepSkyBlue") - 1));
border();
show(COLORS.floorEntry(rgb("DeepSkyBlue") - 1));
border();
show(toLime.descendingMap());
border();
show(COLORS.tailMap(rgb("MistyRose"), true));
border();
show(COLORS.subMap(
rgb("Orchid"), true,
rgb("DarkSalmon"), false));
}
}
/* Output:
0x000000: Black
******************************
0xFFFFFF: White
******************************
0x000000: Black
0x000080: Navy
0x00008B: DarkBlue
0x0000CD: MediumBlue
0x0000FF: Blue
0x006400: DarkGreen
0x008000: Green
0x008080: Teal
0x008B8B: DarkCyan
0x00BFFF: DeepSkyBlue
0x00CED1: DarkTurquoise
0x00FA9A: MediumSpringGreen
0x00FF00: Lime
******************************
0x00BFFF: DeepSkyBlue
******************************
0x008B8B: DarkCyan
******************************
0x00FF00: Lime
0x00FA9A: MediumSpringGreen
0x00CED1: DarkTurquoise
0x00BFFF: DeepSkyBlue
0x008B8B: DarkCyan
0x008080: Teal
0x008000: Green
0x006400: DarkGreen
0x0000FF: Blue
0x0000CD: MediumBlue
0x00008B: DarkBlue
0x000080: Navy
0x000000: Black
******************************
0xFFE4E1: MistyRose
0xFFEBCD: BlanchedAlmond
0xFFEFD5: PapayaWhip
0xFFF0F5: LavenderBlush
0xFFF5EE: SeaShell
0xFFF8DC: Cornsilk
0xFFFACD: LemonChiffon
0xFFFAF0: FloralWhite
0xFFFAFA: Snow
0xFFFF00: Yellow
0xFFFFE0: LightYellow
0xFFFFF0: Ivory
0xFFFFFF: White
******************************
0xDA70D6: Orchid
0xDAA520: GoldenRod
0xDB7093: PaleVioletRed
0xDC143C: Crimson
0xDCDCDC: Gainsboro
0xDDA0DD: Plum
0xDEB887: BurlyWood
0xE0FFFF: LightCyan
0xE6E6FA: Lavender
*/
// collectiontopics/FillingLists.java
// Collections.fill() & Collections.nCopies()
import java.util.*;
class StringAddress {
private String s;
StringAddress(String s) { this.s = s; }
@Override
public String toString() {
return super.toString() + " " + s;
}
}
public class FillingLists {
public static void main(String[] args) {
List<StringAddress> list = new ArrayList<>(
Collections.nCopies(4,
new StringAddress("Hello")));
System.out.println(list);
Collections.fill(list,
new StringAddress("World!"));
System.out.println(list);
}
}
/* Output:
[StringAddress@15db9742 Hello, StringAddress@15db9742
Hello, StringAddress@15db9742 Hello,
StringAddress@15db9742 Hello]
[StringAddress@6d06d69c World!, StringAddress@6d06d69c
World!, StringAddress@6d06d69c World!,
StringAddress@6d06d69c World!]
*/
// collectiontopics/SuppliersCollectionTest.java
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
import onjava.*;
class Government implements Supplier<String> {
static String[] foundation = (
"strange women lying in ponds " +
"distributing swords is no basis " +
"for a system of government").split(" ");
private int index;
@Override
public String get() {
return foundation[index++];
}
}
public class SuppliersCollectionTest {
public static void main(String[] args) {
// Suppliers class from the Generics chapter:
Set<String> set = Suppliers.create(
LinkedHashSet::new, new Government(), 15);
System.out.println(set);
List<String> list = Suppliers.create(
LinkedList::new, new Government(), 15);
System.out.println(list);
list = new ArrayList<>();
Suppliers.fill(list, new Government(), 15);
System.out.println(list);
// Or we can use Streams:
set = Arrays.stream(Government.foundation)
.collect(Collectors.toSet());
System.out.println(set);
list = Arrays.stream(Government.foundation)
.collect(Collectors.toList());
System.out.println(list);
list = Arrays.stream(Government.foundation)
.collect(Collectors
.toCollection(LinkedList::new));
System.out.println(list);
set = Arrays.stream(Government.foundation)
.collect(Collectors
.toCollection(LinkedHashSet::new));
System.out.println(set);
}
}
/* Output:
[strange, women, lying, in, ponds, distributing,
swords, is, no, basis, for, a, system, of, government]
[strange, women, lying, in, ponds, distributing,
swords, is, no, basis, for, a, system, of, government]
[strange, women, lying, in, ponds, distributing,
swords, is, no, basis, for, a, system, of, government]
[ponds, no, a, in, swords, for, is, basis, strange,
system, government, distributing, of, women, lying]
[strange, women, lying, in, ponds, distributing,
swords, is, no, basis, for, a, system, of, government]
[strange, women, lying, in, ponds, distributing,
swords, is, no, basis, for, a, system, of, government]
[strange, women, lying, in, ponds, distributing,
swords, is, no, basis, for, a, system, of, government]
*/
// onjava/Pair.java
package onjava;
public class Pair<K, V> {
public final K key;
public final V value;
public Pair(K k, V v) {
key = k;
value = v;
}
public K key() { return key; }
public V value() { return value; }
public static <K,V> Pair<K, V> make(K k, V v) {
return new Pair<K,V>(k, v);
}
}
// collectiontopics/StreamFillMaps.java
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
import onjava.*;
class Letters
implements Supplier<Pair<Integer,String>> {
private int number = 1;
private char letter = 'A';
@Override
public Pair<Integer,String> get() {
return new Pair<>(number++, "" + letter++);
}
}
public class StreamFillMaps {
public static void main(String[] args) {
Map<Integer,String> m =
Stream.generate(new Letters())
.limit(11)
.collect(Collectors
.toMap(Pair::key, Pair::value));
System.out.println(m);
// Two separate Suppliers:
Rand.String rs = new Rand.String(3);
Count.Character cc = new Count.Character();
Map<Character,String> mcs = Stream.generate(
() -> Pair.make(cc.get(), rs.get()))
.limit(8)
.collect(Collectors
.toMap(Pair::key, Pair::value));
System.out.println(mcs);
// A key Supplier and a single value:
Map<Character,String> mcs2 = Stream.generate(
() -> Pair.make(cc.get(), "Val"))
.limit(8)
.collect(Collectors
.toMap(Pair::key, Pair::value));
System.out.println(mcs2);
}
}
/* Output:
{1=A, 2=B, 3=C, 4=D, 5=E, 6=F, 7=G, 8=H, 9=I, 10=J,
11=K}
{b=btp, c=enp, d=ccu, e=xsz, f=gvg, g=mei, h=nne,
i=elo}
{p=Val, q=Val, j=Val, k=Val, l=Val, m=Val, n=Val,
o=Val}
*/
// onjava/FillMap.java
package onjava;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
public class FillMap {
public static <K, V> Map<K,V>
basic(Supplier<Pair<K,V>> pairGen, int size) {
return Stream.generate(pairGen)
.limit(size)
.collect(Collectors
.toMap(Pair::key, Pair::value));
}
public static <K, V> Map<K,V>
basic(Supplier<K> keyGen,
Supplier<V> valueGen, int size) {
return Stream.generate(
() -> Pair.make(keyGen.get(), valueGen.get()))
.limit(size)
.collect(Collectors
.toMap(Pair::key, Pair::value));
}
public static <K, V, M extends Map<K,V>>
M create(Supplier<K> keyGen,
Supplier<V> valueGen,
Supplier<M> mapSupplier, int size) {
return Stream.generate( () ->
Pair.make(keyGen.get(), valueGen.get()))
.limit(size)
.collect(Collectors
.toMap(Pair::key, Pair::value,
(k, v) -> k, mapSupplier));
}
}
// onjava/Countries.java
// "Flyweight" Maps and Lists of sample data
// {java onjava.Countries}
package onjava;
import java.util.*;
public class Countries {
public static final String[][] DATA = {
// Africa
{"ALGERIA","Algiers"},
{"ANGOLA","Luanda"},
{"BENIN","Porto-Novo"},
{"BOTSWANA","Gaberone"},
{"BURKINA FASO","Ouagadougou"},
{"BURUNDI","Bujumbura"},
{"CAMEROON","Yaounde"},
{"CAPE VERDE","Praia"},
{"CENTRAL AFRICAN REPUBLIC","Bangui"},
{"CHAD","N'djamena"},
{"COMOROS","Moroni"},
{"CONGO","Brazzaville"},
{"DJIBOUTI","Dijibouti"},
{"EGYPT","Cairo"},
{"EQUATORIAL GUINEA","Malabo"},
{"ERITREA","Asmara"},
{"ETHIOPIA","Addis Ababa"},
{"GABON","Libreville"},
{"THE GAMBIA","Banjul"},
{"GHANA","Accra"},
{"GUINEA","Conakry"},
{"BISSAU","Bissau"},
{"COTE D'IVOIR (IVORY COAST)","Yamoussoukro"},
{"KENYA","Nairobi"},
{"LESOTHO","Maseru"},
{"LIBERIA","Monrovia"},
{"LIBYA","Tripoli"},
{"MADAGASCAR","Antananarivo"},
{"MALAWI","Lilongwe"},
{"MALI","Bamako"},
{"MAURITANIA","Nouakchott"},
{"MAURITIUS","Port Louis"},
{"MOROCCO","Rabat"},
{"MOZAMBIQUE","Maputo"},
{"NAMIBIA","Windhoek"},
{"NIGER","Niamey"},
{"NIGERIA","Abuja"},
{"RWANDA","Kigali"},
{"SAO TOME E PRINCIPE","Sao Tome"},
{"SENEGAL","Dakar"},
{"SEYCHELLES","Victoria"},
{"SIERRA LEONE","Freetown"},
{"SOMALIA","Mogadishu"},
{"SOUTH AFRICA","Pretoria/Cape Town"},
{"SUDAN","Khartoum"},
{"SWAZILAND","Mbabane"},
{"TANZANIA","Dodoma"},
{"TOGO","Lome"},
{"TUNISIA","Tunis"},
{"UGANDA","Kampala"},
{"DEMOCRATIC REPUBLIC OF THE CONGO (ZAIRE)",
"Kinshasa"},
{"ZAMBIA","Lusaka"},
{"ZIMBABWE","Harare"},
// Asia
{"AFGHANISTAN","Kabul"},
{"BAHRAIN","Manama"},
{"BANGLADESH","Dhaka"},
{"BHUTAN","Thimphu"},
{"BRUNEI","Bandar Seri Begawan"},
{"CAMBODIA","Phnom Penh"},
{"CHINA","Beijing"},
{"CYPRUS","Nicosia"},
{"INDIA","New Delhi"},
{"INDONESIA","Jakarta"},
{"IRAN","Tehran"},
{"IRAQ","Baghdad"},
{"ISRAEL","Jerusalem"},
{"JAPAN","Tokyo"},
{"JORDAN","Amman"},
{"KUWAIT","Kuwait City"},
{"LAOS","Vientiane"},
{"LEBANON","Beirut"},
{"MALAYSIA","Kuala Lumpur"},
{"THE MALDIVES","Male"},
{"MONGOLIA","Ulan Bator"},
{"MYANMAR (BURMA)","Rangoon"},
{"NEPAL","Katmandu"},
{"NORTH KOREA","P'yongyang"},
{"OMAN","Muscat"},
{"PAKISTAN","Islamabad"},
{"PHILIPPINES","Manila"},
{"QATAR","Doha"},
{"SAUDI ARABIA","Riyadh"},
{"SINGAPORE","Singapore"},
{"SOUTH KOREA","Seoul"},
{"SRI LANKA","Colombo"},
{"SYRIA","Damascus"},
{"TAIWAN (REPUBLIC OF CHINA)","Taipei"},
{"THAILAND","Bangkok"},
{"TURKEY","Ankara"},
{"UNITED ARAB EMIRATES","Abu Dhabi"},
{"VIETNAM","Hanoi"},
{"YEMEN","Sana'a"},
// Australia and Oceania
{"AUSTRALIA","Canberra"},
{"FIJI","Suva"},
{"KIRIBATI","Bairiki"},
{"MARSHALL ISLANDS","Dalap-Uliga-Darrit"},
{"MICRONESIA","Palikir"},
{"NAURU","Yaren"},
{"NEW ZEALAND","Wellington"},
{"PALAU","Koror"},
{"PAPUA NEW GUINEA","Port Moresby"},
{"SOLOMON ISLANDS","Honaira"},
{"TONGA","Nuku'alofa"},
{"TUVALU","Fongafale"},
{"VANUATU","Port Vila"},
{"WESTERN SAMOA","Apia"},
// Eastern Europe and former USSR
{"ARMENIA","Yerevan"},
{"AZERBAIJAN","Baku"},
{"BELARUS (BYELORUSSIA)","Minsk"},
{"BULGARIA","Sofia"},
{"GEORGIA","Tbilisi"},
{"KAZAKSTAN","Almaty"},
{"KYRGYZSTAN","Alma-Ata"},
{"MOLDOVA","Chisinau"},
{"RUSSIA","Moscow"},
{"TAJIKISTAN","Dushanbe"},
{"TURKMENISTAN","Ashkabad"},
{"UKRAINE","Kyiv"},
{"UZBEKISTAN","Tashkent"},
// Europe
{"ALBANIA","Tirana"},
{"ANDORRA","Andorra la Vella"},
{"AUSTRIA","Vienna"},
{"BELGIUM","Brussels"},
{"BOSNIA-HERZEGOVINA","Sarajevo"},
{"CROATIA","Zagreb"},
{"CZECH REPUBLIC","Prague"},
{"DENMARK","Copenhagen"},
{"ESTONIA","Tallinn"},
{"FINLAND","Helsinki"},
{"FRANCE","Paris"},
{"GERMANY","Berlin"},
{"GREECE","Athens"},
{"HUNGARY","Budapest"},
{"ICELAND","Reykjavik"},
{"IRELAND","Dublin"},
{"ITALY","Rome"},
{"LATVIA","Riga"},
{"LIECHTENSTEIN","Vaduz"},
{"LITHUANIA","Vilnius"},
{"LUXEMBOURG","Luxembourg"},
{"MACEDONIA","Skopje"},
{"MALTA","Valletta"},
{"MONACO","Monaco"},
{"MONTENEGRO","Podgorica"},
{"THE NETHERLANDS","Amsterdam"},
{"NORWAY","Oslo"},
{"POLAND","Warsaw"},
{"PORTUGAL","Lisbon"},
{"ROMANIA","Bucharest"},
{"SAN MARINO","San Marino"},
{"SERBIA","Belgrade"},
{"SLOVAKIA","Bratislava"},
{"SLOVENIA","Ljuijana"},
{"SPAIN","Madrid"},
{"SWEDEN","Stockholm"},
{"SWITZERLAND","Berne"},
{"UNITED KINGDOM","London"},
{"VATICAN CITY","Vatican City"},
// North and Central America
{"ANTIGUA AND BARBUDA","Saint John's"},
{"BAHAMAS","Nassau"},
{"BARBADOS","Bridgetown"},
{"BELIZE","Belmopan"},
{"CANADA","Ottawa"},
{"COSTA RICA","San Jose"},
{"CUBA","Havana"},
{"DOMINICA","Roseau"},
{"DOMINICAN REPUBLIC","Santo Domingo"},
{"EL SALVADOR","San Salvador"},
{"GRENADA","Saint George's"},
{"GUATEMALA","Guatemala City"},
{"HAITI","Port-au-Prince"},
{"HONDURAS","Tegucigalpa"},
{"JAMAICA","Kingston"},
{"MEXICO","Mexico City"},
{"NICARAGUA","Managua"},
{"PANAMA","Panama City"},
{"ST. KITTS AND NEVIS","Basseterre"},
{"ST. LUCIA","Castries"},
{"ST. VINCENT AND THE GRENADINES","Kingstown"},
{"UNITED STATES OF AMERICA","Washington, D.C."},
// South America
{"ARGENTINA","Buenos Aires"},
{"BOLIVIA","Sucre (legal)/La Paz(administrative)"},
{"BRAZIL","Brasilia"},
{"CHILE","Santiago"},
{"COLOMBIA","Bogota"},
{"ECUADOR","Quito"},
{"GUYANA","Georgetown"},
{"PARAGUAY","Asuncion"},
{"PERU","Lima"},
{"SURINAME","Paramaribo"},
{"TRINIDAD AND TOBAGO","Port of Spain"},
{"URUGUAY","Montevideo"},
{"VENEZUELA","Caracas"},
};
// Use AbstractMap by implementing entrySet()
private static class FlyweightMap
extends AbstractMap<String,String> {
private static class Entry
implements Map.Entry<String,String> {
int index;
Entry(int index) { this.index = index; }
@Override
public boolean equals(Object o) {
return o instanceof FlyweightMap &&
Objects.equals(DATA[index][0], o);
}
@Override
public int hashCode() {
return Objects.hashCode(DATA[index][0]);
}
@Override
public String getKey() { return DATA[index][0]; }
@Override
public String getValue() {
return DATA[index][1];
}
@Override
public String setValue(String value) {
throw new UnsupportedOperationException();
}
}
// Implement size() & iterator() for AbstractSet:
static class EntrySet
extends AbstractSet<Map.Entry<String,String>> {
private int size;
EntrySet(int size) {
if(size < 0)
this.size = 0;
// Can't be any bigger than the array:
else if(size > DATA.length)
this.size = DATA.length;
else
this.size = size;
}
@Override
public int size() { return size; }
private class Iter
implements Iterator<Map.Entry<String,String>> {
// Only one Entry object per Iterator:
private Entry entry = new Entry(-1);
@Override
public boolean hasNext() {
return entry.index < size - 1;
}
@Override
public Map.Entry<String,String> next() {
entry.index++;
return entry;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
@Override
public
Iterator<Map.Entry<String,String>> iterator() {
return new Iter();
}
}
private static
Set<Map.Entry<String,String>> entries =
new EntrySet(DATA.length);
@Override
public Set<Map.Entry<String,String>> entrySet() {
return entries;
}
}
// Create a partial map of 'size' countries:
static Map<String,String> select(final int size) {
return new FlyweightMap() {
@Override
public Set<Map.Entry<String,String>> entrySet() {
return new EntrySet(size);
}
};
}
static Map<String,String> map = new FlyweightMap();
public static Map<String,String> capitals() {
return map; // The entire map
}
public static Map<String,String> capitals(int size) {
return select(size); // A partial map
}
static List<String> names =
new ArrayList<>(map.keySet());
// All the names:
public static List<String> names() { return names; }
// A partial list:
public static List<String> names(int size) {
return new ArrayList<>(select(size).keySet());
}
public static void main(String[] args) {
System.out.println(capitals(10));
System.out.println(names(10));
System.out.println(new HashMap<>(capitals(3)));
System.out.println(
new LinkedHashMap<>(capitals(3)));
System.out.println(new TreeMap<>(capitals(3)));
System.out.println(new Hashtable<>(capitals(3)));
System.out.println(new HashSet<>(names(6)));
System.out.println(new LinkedHashSet<>(names(6)));
System.out.println(new TreeSet<>(names(6)));
System.out.println(new ArrayList<>(names(6)));
System.out.println(new LinkedList<>(names(6)));
System.out.println(capitals().get("BRAZIL"));
}
}
/* Output:
{ALGERIA=Algiers, ANGOLA=Luanda, BENIN=Porto-Novo,
BOTSWANA=Gaberone, BURKINA FASO=Ouagadougou,
BURUNDI=Bujumbura, CAMEROON=Yaounde, CAPE VERDE=Praia,
CENTRAL AFRICAN REPUBLIC=Bangui, CHAD=N'djamena}
[ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO,
BURUNDI, CAMEROON, CAPE VERDE, CENTRAL AFRICAN
REPUBLIC, CHAD]
{BENIN=Porto-Novo, ANGOLA=Luanda, ALGERIA=Algiers}
{ALGERIA=Algiers, ANGOLA=Luanda, BENIN=Porto-Novo}
{ALGERIA=Algiers, ANGOLA=Luanda, BENIN=Porto-Novo}
{ALGERIA=Algiers, ANGOLA=Luanda, BENIN=Porto-Novo}
[BENIN, BOTSWANA, ANGOLA, BURKINA FASO, ALGERIA,
BURUNDI]
[ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO,
BURUNDI]
[ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO,
BURUNDI]
[ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO,
BURUNDI]
[ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO,
BURUNDI]
Brasilia
*/
// collectiontopics/CollectionMethods.java
// Things you can do with all Collections
import java.util.*;
import static onjava.HTMLColors.*;
public class CollectionMethods {
public static void main(String[] args) {
Collection<String> c =
new ArrayList<>(LIST.subList(0, 4));
c.add("ten");
c.add("eleven");
show(c);
border();
// Make an array from the List:
Object[] array = c.toArray();
// Make a String array from the List:
String[] str = c.toArray(new String[0]);
// Find max and min elements; this means
// different things depending on the way
// the Comparable interface is implemented:
System.out.println(
"Collections.max(c) = " + Collections.max(c));
System.out.println(
"Collections.min(c) = " + Collections.min(c));
border();
// Add a Collection to another Collection
Collection<String> c2 =
new ArrayList<>(LIST.subList(10, 14));
c.addAll(c2);
show(c);
border();
c.remove(LIST.get(0));
show(c);
border();
// Remove all components that are
// in the argument collection:
c.removeAll(c2);
show(c);
border();
c.addAll(c2);
show(c);
border();
// Is an element in this Collection?
String val = LIST.get(3);
System.out.println(
"c.contains(" + val + ") = " + c.contains(val));
// Is a Collection in this Collection?
System.out.println(
"c.containsAll(c2) = " + c.containsAll(c2));
Collection<String> c3 =
((List<String>)c).subList(3, 5);
// Keep all the elements that are in both
// c2 and c3 (an intersection of sets):
c2.retainAll(c3);
show(c2);
// Throw away all the elements
// in c2 that also appear in c3:
c2.removeAll(c3);
System.out.println(
"c2.isEmpty() = " + c2.isEmpty());
border();
// Functional operation:
c = new ArrayList<>(LIST);
c.removeIf(s -> !s.startsWith("P"));
c.removeIf(s -> s.startsWith("Pale"));
// Stream operation:
c.stream().forEach(System.out::println);
c.clear(); // Remove all elements
System.out.println("after c.clear():" + c);
}
}
/* Output:
AliceBlue
AntiqueWhite
Aquamarine
Azure
ten
eleven
******************************
Collections.max(c) = ten
Collections.min(c) = AliceBlue
******************************
AliceBlue
AntiqueWhite
Aquamarine
Azure
ten
eleven
Brown
BurlyWood
CadetBlue
Chartreuse
******************************
AntiqueWhite
Aquamarine
Azure
ten
eleven
Brown
BurlyWood
CadetBlue
Chartreuse
******************************
AntiqueWhite
Aquamarine
Azure
ten
eleven
******************************
AntiqueWhite
Aquamarine
Azure
ten
eleven
Brown
BurlyWood
CadetBlue
Chartreuse
******************************
c.contains(Azure) = true
c.containsAll(c2) = true
c2.isEmpty() = true
******************************
PapayaWhip
PeachPuff
Peru
Pink
Plum
PowderBlue
Purple
after c.clear():[]
*/
// collectiontopics/Unsupported.java
// Unsupported operations in Java collections
import java.util.*;
public class Unsupported {
static void
check(String description, Runnable tst) {
try {
tst.run();
} catch(Exception e) {
System.out.println(description + "(): " + e);
}
}
static void test(String msg, List<String> list) {
System.out.println("--- " + msg + " ---");
Collection<String> c = list;
Collection<String> subList = list.subList(1,8);
// Copy of the sublist:
Collection<String> c2 = new ArrayList<>(subList);
check("retainAll", () -> c.retainAll(c2));
check("removeAll", () -> c.removeAll(c2));
check("clear", () -> c.clear());
check("add", () -> c.add("X"));
check("addAll", () -> c.addAll(c2));
check("remove", () -> c.remove("C"));
// The List.set() method modifies the value but
// doesn't change the size of the data structure:
check("List.set", () -> list.set(0, "X"));
}
public static void main(String[] args) {
List<String> list = Arrays.asList(
"A B C D E F G H I J K L".split(" "));
test("Modifiable Copy", new ArrayList<>(list));
test("Arrays.asList()", list);
test("unmodifiableList()",
Collections.unmodifiableList(
new ArrayList<>(list)));
}
}
/* Output:
--- Modifiable Copy ---
--- Arrays.asList() ---
retainAll(): java.lang.UnsupportedOperationException
removeAll(): java.lang.UnsupportedOperationException
clear(): java.lang.UnsupportedOperationException
add(): java.lang.UnsupportedOperationException
addAll(): java.lang.UnsupportedOperationException
remove(): java.lang.UnsupportedOperationException
--- unmodifiableList() ---
retainAll(): java.lang.UnsupportedOperationException
removeAll(): java.lang.UnsupportedOperationException
clear(): java.lang.UnsupportedOperationException
add(): java.lang.UnsupportedOperationException
addAll(): java.lang.UnsupportedOperationException
remove(): java.lang.UnsupportedOperationException
List.set(): java.lang.UnsupportedOperationException
*/
// collectiontopics/SortedSetDemo.java
import java.util.*;
import static java.util.stream.Collectors.*;
public class SortedSetDemo {
public static void main(String[] args) {
SortedSet<String> sortedSet =
Arrays.stream(
"one two three four five six seven eight"
.split(" "))
.collect(toCollection(TreeSet::new));
System.out.println(sortedSet);
String low = sortedSet.first();
String high = sortedSet.last();
System.out.println(low);
System.out.println(high);
Iterator<String> it = sortedSet.iterator();
for(int i = 0; i <= 6; i++) {
if(i == 3) low = it.next();
if(i == 6) high = it.next();
else it.next();
}
System.out.println(low);
System.out.println(high);
System.out.println(sortedSet.subSet(low, high));
System.out.println(sortedSet.headSet(high));
System.out.println(sortedSet.tailSet(low));
}
}
/* Output:
[eight, five, four, one, seven, six, three, two]
eight
two
one
two
[one, seven, six, three]
[eight, five, four, one, seven, six, three]
[one, seven, six, three, two]
*/
// collectiontopics/QueueBehavior.java
// Compares basic behavior
import java.util.*;
import java.util.stream.*;
import java.util.concurrent.*;
public class QueueBehavior {
static Stream<String> strings() {
return Arrays.stream(
("one two three four five six seven " +
"eight nine ten").split(" "));
}
static void test(int id, Queue<String> queue) {
System.out.print(id + ": ");
strings().map(queue::offer).count();
while(queue.peek() != null)
System.out.print(queue.remove() + " ");
System.out.println();
}
public static void main(String[] args) {
int count = 10;
test(1, new LinkedList<>());
test(2, new PriorityQueue<>());
test(3, new ArrayBlockingQueue<>(count));
test(4, new ConcurrentLinkedQueue<>());
test(5, new LinkedBlockingQueue<>());
test(6, new PriorityBlockingQueue<>());
test(7, new ArrayDeque<>());
test(8, new ConcurrentLinkedDeque<>());
test(9, new LinkedBlockingDeque<>());
test(10, new LinkedTransferQueue<>());
test(11, new SynchronousQueue<>());
}
}
/* Output:
1: one two three four five six seven eight nine ten
2: eight five four nine one seven six ten three two
3: one two three four five six seven eight nine ten
4: one two three four five six seven eight nine ten
5: one two three four five six seven eight nine ten
6: eight five four nine one seven six ten three two
7: one two three four five six seven eight nine ten
8: one two three four five six seven eight nine ten
9: one two three four five six seven eight nine ten
10: one two three four five six seven eight nine ten
11:
*/
// collectiontopics/ToDoList.java
// A more complex use of PriorityQueue
import java.util.*;
class ToDoItem implements Comparable<ToDoItem> {
private char primary;
private int secondary;
private String item;
ToDoItem(String td, char pri, int sec) {
primary = pri;
secondary = sec;
item = td;
}
@Override
public int compareTo(ToDoItem arg) {
if(primary > arg.primary)
return +1;
if(primary == arg.primary)
if(secondary > arg.secondary)
return +1;
else if(secondary == arg.secondary)
return 0;
return -1;
}
@Override
public String toString() {
return Character.toString(primary) +
secondary + ": " + item;
}
}
class ToDoList {
public static void main(String[] args) {
PriorityQueue<ToDoItem> toDo =
new PriorityQueue<>();
toDo.add(new ToDoItem("Empty trash", 'C', 4));
toDo.add(new ToDoItem("Feed dog", 'A', 2));
toDo.add(new ToDoItem("Feed bird", 'B', 7));
toDo.add(new ToDoItem("Mow lawn", 'C', 3));
toDo.add(new ToDoItem("Water lawn", 'A', 1));
toDo.add(new ToDoItem("Feed cat", 'B', 1));
while(!toDo.isEmpty())
System.out.println(toDo.remove());
}
}
/* Output:
A1: Water lawn
A2: Feed dog
B1: Feed cat
B7: Feed bird
C3: Mow lawn
C4: Empty trash
*/
// collectiontopics/AssociativeArray.java
// Associates keys with values
public class AssociativeArray<K, V> {
private Object[][] pairs;
private int index;
public AssociativeArray(int length) {
pairs = new Object[length][2];
}
public void put(K key, V value) {
if(index >= pairs.length)
throw new ArrayIndexOutOfBoundsException();
pairs[index++] = new Object[]{ key, value };
}
@SuppressWarnings("unchecked")
public V get(K key) {
for(int i = 0; i < index; i++)
if(key.equals(pairs[i][0]))
return (V)pairs[i][1];
return null; // Did not find key
}
@Override
public String toString() {
StringBuilder result = new StringBuilder();
for(int i = 0; i < index; i++) {
result.append(pairs[i][0].toString());
result.append(" : ");
result.append(pairs[i][1].toString());
if(i < index - 1)
result.append("\n");
}
return result.toString();
}
public static void main(String[] args) {
AssociativeArray<String,String> map =
new AssociativeArray<>(6);
map.put("sky", "blue");
map.put("grass", "green");
map.put("ocean", "dancing");
map.put("tree", "tall");
map.put("earth", "brown");
map.put("sun", "warm");
try {
map.put("extra", "object"); // Past the end
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("Too many objects!");
}
System.out.println(map);
System.out.println(map.get("ocean"));
}
}
/* Output:
Too many objects!
sky : blue
grass : green
ocean : dancing
tree : tall
earth : brown
sun : warm
dancing
*/
// collectiontopics/SortedMapDemo.java
// What you can do with a TreeMap
import java.util.*;
import onjava.*;
public class SortedMapDemo {
public static void main(String[] args) {
TreeMap<Integer,String> sortedMap =
new TreeMap<>(new CountMap(10));
System.out.println(sortedMap);
Integer low = sortedMap.firstKey();
Integer high = sortedMap.lastKey();
System.out.println(low);
System.out.println(high);
Iterator<Integer> it =
sortedMap.keySet().iterator();
for(int i = 0; i <= 6; i++) {
if(i == 3) low = it.next();
if(i == 6) high = it.next();
else it.next();
}
System.out.println(low);
System.out.println(high);
System.out.println(sortedMap.subMap(low, high));
System.out.println(sortedMap.headMap(high));
System.out.println(sortedMap.tailMap(low));
}
}
/* Output:
{0=A0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0, 6=G0, 7=H0, 8=I0,
9=J0}
0
9
3
7
{3=D0, 4=E0, 5=F0, 6=G0}
{0=A0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0, 6=G0}
{3=D0, 4=E0, 5=F0, 6=G0, 7=H0, 8=I0, 9=J0}
*/
// collectiontopics/LinkedHashMapDemo.java
// What you can do with a LinkedHashMap
import java.util.*;
import onjava.*;
public class LinkedHashMapDemo {
public static void main(String[] args) {
LinkedHashMap<Integer,String> linkedMap =
new LinkedHashMap<>(new CountMap(9));
System.out.println(linkedMap);
// Least-recently-used order:
linkedMap =
new LinkedHashMap<>(16, 0.75f, true);
linkedMap.putAll(new CountMap(9));
System.out.println(linkedMap);
for(int i = 0; i < 6; i++)
linkedMap.get(i);
System.out.println(linkedMap);
linkedMap.get(0);
System.out.println(linkedMap);
}
}
/* Output:
{0=A0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0, 6=G0, 7=H0, 8=I0}
{0=A0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0, 6=G0, 7=H0, 8=I0}
{6=G0, 7=H0, 8=I0, 0=A0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0}
{6=G0, 7=H0, 8=I0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0, 0=A0}
*/
// collectiontopics/Utilities.java
// Simple demonstrations of the Collections utilities
import java.util.*;
public class Utilities {
static List<String> list = Arrays.asList(
"one Two three Four five six one".split(" "));
public static void main(String[] args) {
System.out.println(list);
System.out.println("'list' disjoint (Four)?: " +
Collections.disjoint(list,
Collections.singletonList("Four")));
System.out.println(
"max: " + Collections.max(list));
System.out.println(
"min: " + Collections.min(list));
System.out.println(
"max w/ comparator: " + Collections.max(list,
String.CASE_INSENSITIVE_ORDER));
System.out.println(
"min w/ comparator: " + Collections.min(list,
String.CASE_INSENSITIVE_ORDER));
List<String> sublist =
Arrays.asList("Four five six".split(" "));
System.out.println("indexOfSubList: " +
Collections.indexOfSubList(list, sublist));
System.out.println("lastIndexOfSubList: " +
Collections.lastIndexOfSubList(list, sublist));
Collections.replaceAll(list, "one", "Yo");
System.out.println("replaceAll: " + list);
Collections.reverse(list);
System.out.println("reverse: " + list);
Collections.rotate(list, 3);
System.out.println("rotate: " + list);
List<String> source =
Arrays.asList("in the matrix".split(" "));
Collections.copy(list, source);
System.out.println("copy: " + list);
Collections.swap(list, 0, list.size() - 1);
System.out.println("swap: " + list);
Collections.shuffle(list, new Random(47));
System.out.println("shuffled: " + list);
Collections.fill(list, "pop");
System.out.println("fill: " + list);
System.out.println("frequency of 'pop': " +
Collections.frequency(list, "pop"));
List<String> dups =
Collections.nCopies(3, "snap");
System.out.println("dups: " + dups);
System.out.println("'list' disjoint 'dups'?: " +
Collections.disjoint(list, dups));
// Getting an old-style Enumeration:
Enumeration<String> e =
Collections.enumeration(dups);
Vector<String> v = new Vector<>();
while(e.hasMoreElements())
v.addElement(e.nextElement());
// Converting an old-style Vector
// to a List via an Enumeration:
ArrayList<String> arrayList =
Collections.list(v.elements());
System.out.println("arrayList: " + arrayList);
}
}
/* Output:
[one, Two, three, Four, five, six, one]
'list' disjoint (Four)?: false
max: three
min: Four
max w/ comparator: Two
min w/ comparator: five
indexOfSubList: 3
lastIndexOfSubList: 3
replaceAll: [Yo, Two, three, Four, five, six, Yo]
reverse: [Yo, six, five, Four, three, Two, Yo]
rotate: [three, Two, Yo, Yo, six, five, Four]
copy: [in, the, matrix, Yo, six, five, Four]
swap: [Four, the, matrix, Yo, six, five, in]
shuffled: [six, matrix, the, Four, Yo, five, in]
fill: [pop, pop, pop, pop, pop, pop, pop]
frequency of 'pop': 7
dups: [snap, snap, snap]
'list' disjoint 'dups'?: true
arrayList: [snap, snap, snap]
*/
// collectiontopics/ListSortSearch.java
// Sorting/searching Lists with Collections utilities
import java.util.*;
public class ListSortSearch {
public static void main(String[] args) {
List<String> list =
new ArrayList<>(Utilities.list);
list.addAll(Utilities.list);
System.out.println(list);
Collections.shuffle(list, new Random(47));
System.out.println("Shuffled: " + list);
// Use ListIterator to trim off last elements:
ListIterator<String> it = list.listIterator(10);
while(it.hasNext()) {
it.next();
it.remove();
}
System.out.println("Trimmed: " + list);
Collections.sort(list);
System.out.println("Sorted: " + list);
String key = list.get(7);
int index = Collections.binarySearch(list, key);
System.out.println(
"Location of " + key + " is " + index +
", list.get(" + index + ") = " +
list.get(index));
Collections.sort(list,
String.CASE_INSENSITIVE_ORDER);
System.out.println(
"Case-insensitive sorted: " + list);
key = list.get(7);
index = Collections.binarySearch(list, key,
String.CASE_INSENSITIVE_ORDER);
System.out.println(
"Location of " + key + " is " + index +
", list.get(" + index + ") = " +
list.get(index));
}
}
/* Output:
[one, Two, three, Four, five, six, one, one, Two,
three, Four, five, six, one]
Shuffled: [Four, five, one, one, Two, six, six, three,
three, five, Four, Two, one, one]
Trimmed: [Four, five, one, one, Two, six, six, three,
three, five]
Sorted: [Four, Two, five, five, one, one, six, six,
three, three]
Location of six is 7, list.get(7) = six
Case-insensitive sorted: [five, five, Four, one, one,
six, six, three, three, Two]
Location of three is 7, list.get(7) = three
*/
// collectiontopics/ReadOnly.java
// Using the Collections.unmodifiable methods
import java.util.*;
import onjava.*;
public class ReadOnly {
static Collection<String> data =
new ArrayList<>(Countries.names(6));
public static void main(String[] args) {
Collection<String> c =
Collections.unmodifiableCollection(
new ArrayList<>(data));
System.out.println(c); // Reading is OK
//- c.add("one"); // Can't change it
List<String> a = Collections.unmodifiableList(
new ArrayList<>(data));
ListIterator<String> lit = a.listIterator();
System.out.println(lit.next()); // Reading is OK
//- lit.add("one"); // Can't change it
Set<String> s = Collections.unmodifiableSet(
new HashSet<>(data));
System.out.println(s); // Reading is OK
//- s.add("one"); // Can't change it
// For a SortedSet:
Set<String> ss =
Collections.unmodifiableSortedSet(
new TreeSet<>(data));
Map<String,String> m =
Collections.unmodifiableMap(
new HashMap<>(Countries.capitals(6)));
System.out.println(m); // Reading is OK
//- m.put("Ralph", "Howdy!");
// For a SortedMap:
Map<String,String> sm =
Collections.unmodifiableSortedMap(
new TreeMap<>(Countries.capitals(6)));
}
}
/* Output:
[ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO,
BURUNDI]
ALGERIA
[BENIN, BOTSWANA, ANGOLA, BURKINA FASO, ALGERIA,
BURUNDI]
{BENIN=Porto-Novo, BOTSWANA=Gaberone, ANGOLA=Luanda,
BURKINA FASO=Ouagadougou, ALGERIA=Algiers,
BURUNDI=Bujumbura}
*/
// collectiontopics/Synchronization.java
// Using the Collections.synchronized methods
import java.util.*;
public class Synchronization {
public static void main(String[] args) {
Collection<String> c =
Collections.synchronizedCollection(
new ArrayList<>());
List<String> list = Collections
.synchronizedList(new ArrayList<>());
Set<String> s = Collections
.synchronizedSet(new HashSet<>());
Set<String> ss = Collections
.synchronizedSortedSet(new TreeSet<>());
Map<String,String> m = Collections
.synchronizedMap(new HashMap<>());
Map<String,String> sm = Collections
.synchronizedSortedMap(new TreeMap<>());
}
}
// collectiontopics/FailFast.java
// Demonstrates the "fail-fast" behavior
import java.util.*;
public class FailFast {
public static void main(String[] args) {
Collection<String> c = new ArrayList<>();
Iterator<String> it = c.iterator();
c.add("An object");
try {
String s = it.next();
} catch(ConcurrentModificationException e) {
System.out.println(e);
}
}
}
/* Output:
java.util.ConcurrentModificationException
*/
// collectiontopics/References.java
// Demonstrates Reference objects
import java.lang.ref.*;
import java.util.*;
class VeryBig {
private static final int SIZE = 10000;
private long[] la = new long[SIZE];
private String ident;
VeryBig(String id) { ident = id; }
@Override
public String toString() { return ident; }
@Override
protected void finalize() {
System.out.println("Finalizing " + ident);
}
}
public class References {
private static ReferenceQueue<VeryBig> rq =
new ReferenceQueue<>();
public static void checkQueue() {
Reference<? extends VeryBig> inq = rq.poll();
if(inq != null)
System.out.println("In queue: " + inq.get());
}
public static void main(String[] args) {
int size = 10;
// Or, choose size via the command line:
if(args.length > 0)
size = Integer.valueOf(args[0]);
LinkedList<SoftReference<VeryBig>> sa =
new LinkedList<>();
for(int i = 0; i < size; i++) {
sa.add(new SoftReference<>(
new VeryBig("Soft " + i), rq));
System.out.println(
"Just created: " + sa.getLast());
checkQueue();
}
LinkedList<WeakReference<VeryBig>> wa =
new LinkedList<>();
for(int i = 0; i < size; i++) {
wa.add(new WeakReference<>(
new VeryBig("Weak " + i), rq));
System.out.println(
"Just created: " + wa.getLast());
checkQueue();
}
SoftReference<VeryBig> s =
new SoftReference<>(new VeryBig("Soft"));
WeakReference<VeryBig> w =
new WeakReference<>(new VeryBig("Weak"));
System.gc();
LinkedList<PhantomReference<VeryBig>> pa =
new LinkedList<>();
for(int i = 0; i < size; i++) {
pa.add(new PhantomReference<>(
new VeryBig("Phantom " + i), rq));
System.out.println(
"Just created: " + pa.getLast());
checkQueue();
}
}
}
/* Output: (First and Last 10 Lines)
Just created: java.lang.ref.SoftReference@15db9742
Just created: java.lang.ref.SoftReference@6d06d69c
Just created: java.lang.ref.SoftReference@7852e922
Just created: java.lang.ref.SoftReference@4e25154f
Just created: java.lang.ref.SoftReference@70dea4e
Just created: java.lang.ref.SoftReference@5c647e05
Just created: java.lang.ref.SoftReference@33909752
Just created: java.lang.ref.SoftReference@55f96302
Just created: java.lang.ref.SoftReference@3d4eac69
Just created: java.lang.ref.SoftReference@42a57993
...________...________...________...________...
Just created: java.lang.ref.PhantomReference@45ee12a7
In queue: null
Just created: java.lang.ref.PhantomReference@330bedb4
In queue: null
Just created: java.lang.ref.PhantomReference@2503dbd3
In queue: null
Just created: java.lang.ref.PhantomReference@4b67cf4d
In queue: null
Just created: java.lang.ref.PhantomReference@7ea987ac
In queue: null
*/
// collectiontopics/CanonicalMapping.java
// Demonstrates WeakHashMap
import java.util.*;
class Element {
private String ident;
Element(String id) { ident = id; }
@Override
public String toString() { return ident; }
@Override
public int hashCode() {
return Objects.hashCode(ident);
}
@Override
public boolean equals(Object r) {
return r instanceof Element &&
Objects.equals(ident, ((Element)r).ident);
}
@Override
protected void finalize() {
System.out.println("Finalizing " +
getClass().getSimpleName() + " " + ident);
}
}
class Key extends Element {
Key(String id) { super(id); }
}
class Value extends Element {
Value(String id) { super(id); }
}
public class CanonicalMapping {
public static void main(String[] args) {
int size = 1000;
// Or, choose size via the command line:
if(args.length > 0)
size = Integer.valueOf(args[0]);
Key[] keys = new Key[size];
WeakHashMap<Key,Value> map =
new WeakHashMap<>();
for(int i = 0; i < size; i++) {
Key k = new Key(Integer.toString(i));
Value v = new Value(Integer.toString(i));
if(i % 3 == 0)
keys[i] = k; // Save as "real" references
map.put(k, v);
}
System.gc();
}
}
// collectiontopics/Enumerations.java
// Java 1.0/1.1 Vector and Enumeration
import java.util.*;
import onjava.*;
public class Enumerations {
public static void main(String[] args) {
Vector<String> v =
new Vector<>(Countries.names(10));
Enumeration<String> e = v.elements();
while(e.hasMoreElements())
System.out.print(e.nextElement() + ", ");
// Produce an Enumeration from a Collection:
e = Collections.enumeration(new ArrayList<>());
}
}
/* Output:
ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO,
BURUNDI, CAMEROON, CAPE VERDE, CENTRAL AFRICAN
REPUBLIC, CHAD,
*/
// collectiontopics/Stacks.java
// Demonstration of Stack Class
import java.util.*;
enum Month { JANUARY, FEBRUARY, MARCH, APRIL,
MAY, JUNE, JULY, AUGUST, SEPTEMBER,
OCTOBER, NOVEMBER }
public class Stacks {
public static void main(String[] args) {
Stack<String> stack = new Stack<>();
for(Month m : Month.values())
stack.push(m.toString());
System.out.println("stack = " + stack);
// Treating a stack as a Vector:
stack.addElement("The last line");
System.out.println(
"element 5 = " + stack.elementAt(5));
System.out.println("popping elements:");
while(!stack.empty())
System.out.print(stack.pop() + " ");
// Using a LinkedList as a Stack:
LinkedList<String> lstack = new LinkedList<>();
for(Month m : Month.values())
lstack.addFirst(m.toString());
System.out.println("lstack = " + lstack);
while(!lstack.isEmpty())
System.out.print(lstack.removeFirst() + " ");
// Using the Stack class from
// the Collections Chapter:
onjava.Stack<String> stack2 =
new onjava.Stack<>();
for(Month m : Month.values())
stack2.push(m.toString());
System.out.println("stack2 = " + stack2);
while(!stack2.isEmpty())
System.out.print(stack2.pop() + " ");
}
}
/* Output:
stack = [JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE,
JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER]
element 5 = JUNE
popping elements:
The last line NOVEMBER OCTOBER SEPTEMBER AUGUST JULY
JUNE MAY APRIL MARCH FEBRUARY JANUARY lstack =
[NOVEMBER, OCTOBER, SEPTEMBER, AUGUST, JULY, JUNE, MAY,
APRIL, MARCH, FEBRUARY, JANUARY]
NOVEMBER OCTOBER SEPTEMBER AUGUST JULY JUNE MAY APRIL
MARCH FEBRUARY JANUARY stack2 = [NOVEMBER, OCTOBER,
SEPTEMBER, AUGUST, JULY, JUNE, MAY, APRIL, MARCH,
FEBRUARY, JANUARY]
NOVEMBER OCTOBER SEPTEMBER AUGUST JULY JUNE MAY APRIL
MARCH FEBRUARY JANUARY
*/
// collectiontopics/Bits.java
// Demonstration of BitSet
import java.util.*;
public class Bits {
public static void printBitSet(BitSet b) {
System.out.println("bits: " + b);
StringBuilder bbits = new StringBuilder();
for(int j = 0; j < b.size() ; j++)
bbits.append(b.get(j) ? "1" : "0");
System.out.println("bit pattern: " + bbits);
}
public static void main(String[] args) {
Random rand = new Random(47);
// Take the LSB of nextInt():
byte bt = (byte)rand.nextInt();
BitSet bb = new BitSet();
for(int i = 7; i >= 0; i--)
if(((1 << i) & bt) != 0)
bb.set(i);
else
bb.clear(i);
System.out.println("byte value: " + bt);
printBitSet(bb);
short st = (short)rand.nextInt();
BitSet bs = new BitSet();
for(int i = 15; i >= 0; i--)
if(((1 << i) & st) != 0)
bs.set(i);
else
bs.clear(i);
System.out.println("short value: " + st);
printBitSet(bs);
int it = rand.nextInt();
BitSet bi = new BitSet();
for(int i = 31; i >= 0; i--)
if(((1 << i) & it) != 0)
bi.set(i);
else
bi.clear(i);
System.out.println("int value: " + it);
printBitSet(bi);
// Test bitsets >= 64 bits:
BitSet b127 = new BitSet();
b127.set(127);
System.out.println("set bit 127: " + b127);
BitSet b255 = new BitSet(65);
b255.set(255);
System.out.println("set bit 255: " + b255);
BitSet b1023 = new BitSet(512);
b1023.set(1023);
b1023.set(1024);
System.out.println("set bit 1023: " + b1023);
}
}
/* Output:
byte value: -107
bits: {0, 2, 4, 7}
bit pattern: 101010010000000000000000000000000000000000
0000000000000000000000
short value: 1302
bits: {1, 2, 4, 8, 10}
bit pattern: 011010001010000000000000000000000000000000
0000000000000000000000
int value: -2014573909
bits: {0, 1, 3, 5, 7, 9, 11, 18, 19, 21, 22, 23, 24,
25, 26, 31}
bit pattern: 110101010101000000110111111000010000000000
0000000000000000000000
set bit 127: {127}
set bit 255: {255}
set bit 1023: {1023, 1024}
*/