CSC8014: Software Development – Advanced Techniques 第二周

2.3 Introduction to the Collections Framework

The Collections Framework

• A unified, generic framework for the representation and manipulation of groups of objects
–Manipulation is independent of representation
• Includes:
–Interfaces that define types of collection
–Abstract implementations for customisation
–General-purpose implementations
–Other implementations for legacy (Vector and Hashtable), or to constrain behaviour (wrappers), etc.
–Utilities to operate on collections and arrays and provide algorithms(sorting, searching etc.)
• Is an exemplar for other module material
·用于表示和操纵对象组的统一通用框架

  • 操纵独立于表示
    ·包括:
  • 定义集合类型的接口
  • 用于定制的抽象实现
  • 通用实施
  • 用于遗留(Vector和Hashtable)或约束行为(包装器)等的其他实现。
  • 对集合和数组进行操作并提供算法(排序,搜索等)的实用程序
    ·是其他模块材料的范例
    在这里插入图片描述• Map does not extend Collection.
    – It defines collection-view methods to access keys, values and entries of a mapping

interface Collection extends Iterable {
int size();
boolean isEmpty();
boolean contains(Object element);
boolean add(E element); // optional
boolean remove(Object element); // optional
// iterator from Iterable interface. Returns an iterator over
elements of type E.
Iterator iterator();
// Bulk and array operations
boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c); // optional boolean removeAll(Collection<?> c); // optional
boolean retainAll(Collection<?> c); // optional
void clear(); // optional
Object[] toArray();
E[] toArray(E[] a);
}

What is an Iterator?

• Can be used to cycle through elements of a collection. It has the following methods:
• hasNext(): Returns true if the iteration has more elements
• next(): Returns the next element in the iteration.
• remove(): Removes from the underlying collection the last element returned by this iterator (optional operation).
• How to use it?
–Create an Iterator object using iterator() method
–Use loop and hasNext()to loop through elements
–Obtain the element using next()
·可用于循环遍历集合的元素。它有以下几种方法:
hasNext():如果迭代有更多元素,则返回true
next():返回迭代中的下一个元素。
remove():从底层集合中删除迭代器返回的最后一个元素(可选操作)。
·如何使用它?

  • 使用iterator()方法创建Iterator对象
  • 使用loop和hasNext()循环遍历元素
  • 使用next()获取元素

Iteration over a collection

• Using a “foreach” statement:
void doSomethingToDates(Collection dates){
for (final Date d : dates) doSomethingToDate(d);
}
• Using the collection’s Iterator:
void forgetThePast(Collection dates) {
final Date today = new Date();
Iterator i = dates.iterator();
while (i.hasNext()) {
final Date date = i.next();
if (date.before(today))
i.remove(); // remove date
}
}

Sets

• A Set is an interface that inherits from Collection interface. It cannot contain duplicate elements
– There are no two elements e1 and e2 such that: e1.equals(e2)
– There is at most one null element
• Based on Set Theory
s1.containsAll(s2) // is s2 a subset of s1
s1.addAll(s2) // s1 = s1 union s2
s1.retainAll(s2) // s1 = s1 intersection s2
s1.removeAll(s2) // s1 = s1 difference s2

• There are no additional Set operations, just additional constraints on some operations. For example:
– The Collection add operation returns true if the Collection is modified as a result
– The Set add operation returns false if the Set already contains the element
»Maintains the semantics of the Collection operation and adds a reason for the operation to fail
·没有额外的Set操作,只是对某些操作的额外约束。举例来说:

  • 如果集合被修改,则集合添加操作返回true
  • 如果Set已包含元素,则Set add操作返回false
    »维护Collection操作的语义并添加操作失败的原因

HashSet

• HashSet is the most commonly used implementation of Set (for unsorted set) – There is TreeSet as well (for sorted set)
• Remember, always program to interfaces
Set uniques = new HashSet<>();
Set duplicates = new HashSet<>();

• Set constructors enforce set semantics
Collection removeDups(Collection c) {
// constructing a set from a collection
// removes any duplicate entries
return new HashSet©;
}
–There will be no duplicate elements in the returned collection

Lists

• A list is an ordered sequence of objects that may contain duplicates
• The user has control over where elements are inserted and can access elements through their index (or position)
• The List interface extends Collection and defines additional operations to work with indexed elements etc.
·列表是可能包含重复项的对象的有序序列
·用户可以控制元素插入的位置,并可以通过元素的索引(或位置)访问元素
List接口扩展了Collection,并定义了额外的操作来处理索引元素等。

interface List extends Collection{
E get(int index);
E set(int index, E element);
void add(int index, E element);
E remove(int index);
boolean addAll(int index, Collection<? extends E> c);
int indexOf(Object obj);
int lastIndexOf(Object obj);
// Iteration
ListIterator listIterator();
ListIterator listIterator(int index);
}

Iteration over a List

• See iteration over a collection
• Or use the ListIterator returned by a List.listIerator() or List.listIterator(int) for iteration from a given position
• ListIterator supports:
– Forward and backward traversal
– The ability to obtain list indexes relative to an iterator position
– Element insertion, removal and setting relative to an iterator position
·查看集合上的迭代
·或者使用List. listIterator()或List.listIterator(int)返回的ListIterator从给定位置进行迭代
· ListIterator支持:

  • 向前和向后遍历
  • 获取相对于迭代器位置的列表索引的能力
  • 相对于迭代器位置的元素插入、移除和设置

• It is possible to convert to and from List and arrays as follows:
–List list = Arrays.asList(array);
–String array[] = list.toArray();
• Arrays is a Utility class that allows manipulation of arrays

Maps

在这里插入图片描述• A Map maps keys to values
• A Map cannot contain duplicate keys (keys are unique)
– The collection of keys is a Set
– Map.put(key, value) replaces any existing entry in the map that has the same key
• One or more keys may map to the same value
• Use HashMap unless require guaranteed key order, in which case use TreeMap
·Map将键映射到值
·Map不能包含重复的键(键是唯一的)

  • 键的集合是一个Set
  • Map.put(key,value)替换map中任何具有相同键的现有条目
    ·一个或多个键可以映射到相同的值
    ·使用HashMap,除非需要保证密钥顺序,在这种情况下使用TreeMap

interface Map<K, V> {
V put(K key, V val); // optional
V get(Object key);
V remove(Object key); // optional
boolean containsKey(Object key);
boolean containsValue(Object value);
int size();
boolean isEmpty();
void putAll(Map<? extends K, ? extends V> t);
// optional
void clear(); // optional
Set keySet();
Collection values();
Set<Map.Entry<K, V>> entrySet();
}
• Nested Map.Entry<K, V> interface represents a {key, value} pair

Map Collection views

• The collection view methods provide three different views of the objects in a mapping:
– keySet returns the Set of keys
– values returns the Collection of values
– entrySet returns the Set of Map.Entry {key, value} pairs
• Each returned Collection is backed by the Map and is Iterable (by definition)
• A Collection returned from a modifiable Map supports element removal operations:
– Collection remove, removeAll, retainAll and clear and Iterator remove
• Returned collections do not support element addition operations (neither add nor addAll). Why?
·集合视图方法提供映射中对象的三种不同视图:

  • keySet返回键集
  • values返回值的集合
  • entrySet返回Map.Entry {key,value}对的集合
    ·每个返回的Collection都由Map支持,并且是Iterable的(根据定义)
    ·从可修改的Map返回的Collection支持元素删除操作:
  • 集合remove、removeAll、retainAll和clear以及Iterator remove
    返回的集合不支持元素添加操作(既不支持add也不支持addAll)。为什么?为什么?

Core Collection implementation hierarchy

在这里插入图片描述在这里插入图片描述• The recommended primary implementations are:
– HashSet for sets
– ArrayList for lists
– HashMap for maps
• LinkedList also implements List (and Queue)
• TreeSet implements SortedSet
• TreeMap implements SortedMap
• Do not use Vector or Hashtable because they always incur a synchronization overhead
• Remember: always program to the interfaces
·建议的主要实现是:

  • HashSet用于集合
  • 用于列表的ArrayList
  • HashMap用于map
    LinkedList也实现了List(和Queue)
    · TreeSet实现了SortedSet
    · TreeMap实现了SortedMap
    ·不要使用Vector或Hashtable,因为它们总是会产生同步开销
    ·记住:始终按照接口编程

Arrays and Collections Utilities

• The Arrays utility class provides static methods to search, sort, fill etc. an array plus the asList method that returns a list view of an array
– see java.util.Arrays Javadocs for details
• The Collections utility class provides static methods to search, sort,shuffle, find max and min values etc.
– see java.util.Collections Javadocs for details
• Collections also provides static factory methods to wrap collections to constrain their behaviour
– Wrappers include unmodifiable and thread safe (synchronized) versions of collections and maps

·Arrays实用程序类提供了用于搜索、排序、填充数组等的静态方法,以及返回数组列表视图的asList方法

  • 有关详细信息,请参见java.util.Arrays Javadocs
    ·Collections实用程序类提供静态方法来搜索,排序,洗牌,查找最大值和最小值等。
  • 有关详细信息,请参见java.util.Collections Javadocs
    · Collections还提供了静态工厂方法来包装集合以约束它们的行为
  • 包装器包括集合和映射的不可修改和线程安全(同步)版本

Sets, maps and immutability

• The behaviour of a Set is undefined if a change to the value of a set element affects the element’s equal comparison
– The Set cannot guarantee the no duplicates invariant
– A SortedSet cannot guarantee correct order
• Avoid holding mutable objects in a Set, including the Map key set
– Use immutable objects for Set elements and Map keys
– Or provide an immutable wrapper for mutable elements
– Or ensure that mutable objects do not change while they belong to a Set
(the most difficult option!)

2.4 Mixins and Strategies patterns (Ordering:Comparator and Comparable)

Ordering objects

• Sorting and comparison depend on a sort order
• In Java, the sort order is specified by implementations of the java.lang.Comparable or java.util.Comparator interfaces
• Classes that have a natural sort order, such as String, implement the mixin Comparable interface:
interface Comparable {
// returns:
// i < 0 if this is less than other
// 0 if this.equals(other)
// i > 0 if this is greater than other
int compareTo(T other);
}
• Sorting an array of objects a that implement Comparable is as simple as this:Arrays.sort(a);

public final class Module implements Comparable {
private final String prefix;
private final int number;
private final int semester;
// constructor, accessors, equals, hashCode
// order by prefix, number and semester
public int compareTo(Module m) {
final int pCmp = prefix.compareTo(m.prefix);
if (pCmp != 0) return pCmp ;
return number != m.number
? number – m.number
: semester – m.semester;
}
}

compareTo and equals

• Ideally, compareTo should be consistent with equals (see Bloch-EJ Item14)
• Classes that depend on compareTo include the sorted collections TreeSet and TreeMap and the utility classes Collections and Arrays, which contain searching and sorting algorithms.
• HashMap, ArrayList and HashSet add elements based on the equals method
• If compareTo is not consistent with equals, then it could produce strange results.
• Why?
·理想情况下,compareTo应该与equals一致(参见Bloch-EJ项目14)
·依赖于compare的类包括排序集合TreeSet和TreeMap以及包含搜索和排序算法的实用程序类Collections和Arrays。
· HashMap、ArrayList和HashSet基于equals方法添加元素
如果compareTo与equals不一致,那么它可能会产生奇怪的结果。
·为什么?

The mixin design pattern

• Mixins express optional or orthogonal behaviour
– Classes implement mixin types in addition to their primary type (or function)
• Example Java library mixins
– Instances of a class that implements Serializable can be serialized to a byte stream
– Instances of a class that implements Cloneable can be cloned
» and do not throw CloneNotSupportedException
– Instances of Comparable can be ordered
• Serializable and Cloneable are also markers
– Marker interfaces have no methods but declare a type (some capability)that implementations support
·混合表示可选或正交行为

  • 类除了实现它们的主类型(或函数)外,还实现了mixin类型
    ·Java库混合示例
  • 实现Serializable的类的对象可以被序列化为字节流
  • 可以克隆实现Cloneable的类的实例
    »并且不要抛出CloneNotSupportedException
  • 可订购可比较的产品
    ·可序列化和可克隆也是标记
  • 标记接口没有方法,但声明了实现支持的类型(某些功能)

A problem with mixins

• Mixins are a common and useful pattern but you have to modify a class to implement the mixin interface
• Only an implementation of Comparable can perform a comparison to order itself with respect to another object
– Good for new classes or for existing classes that you control and can retrofit with the Comparable interface
– Not so good for classes you do not control
• So the problem is:
– how do you get the desired behaviour provided by a mixin without modifying a class?
– How can you order instances of a class that does not implement
Comparable without modifying the class?

The strategy design pattern

• The answer is the strategy design pattern
– Use when cannot modify a class or when not implementing
normal/expected behaviour
• A strategy is a separate implementation of an interface that provides the
desired orthogonal behaviour
– E.g. Comparator compares two objects as opposed to an object doing
the comparison itself (by implementing Comparable)
– Implementations of Comparator often provide alternative orderings

Implementing Comparator

• An implementation of the strategy interface Comparator can be used to specify a sort order for objects of a given type.
interface Comparator {
// returns:
// i < 0 if obj1 is less than obj2
// 0 if obj1.equals(obj2)
// i > 0 if obj1 is greater than obj2
int compare(T obj1, T obj2);
}
• A Comparator can be passed to a sort method (Collection.sort(), Arrays.sort()) to sort lists and
arrays according to the order induced by the specified comparator.
• A Comparator instance should be passed to the constructor of SortedSet and
SortedMap implementations to order them according to the order induced by the specified comparator.
• Ideally, Comparator should be consistent with equals

public final class ModuleByStage
implements Comparator {
public ModuleByStage () { }
// order by module semester, prefix, number
public int compare(Module m1, Module m2) {
final int sCmp
= m1.getSemester() – m2.getSemester();
if (sCmp != 0) return sCmp;
final int pCmp
= m1.getPrefix().compareTo(m2.getPrefix());
return pCmp != 0
? pCmp
: m1.getNumber() - m2.getNumber();
}
}

import java.util.*;
class StringSort implements Comparator {
public int compare(String s1, String s2){
return s1.toLowerCase().compareTo(s2.toLowerCase());
}
public static void main(String args[]) {
List list = Arrays.asList(args);
Collections.sort(list); // default String sort
System.out.println(list);
Collections.sort(list, new StringSort()); //case independent String sort
System.out.println(list);
}
}

Mixins versus Strategies

• Mixins and strategies both have their place
– Not all classes can implement or be retrofitted with a mixin
– Not all classes will expose sufficient information to apply a strategy
» There may not be public methods that can be used to implement the strategy’s functionality

SortedSet and SortedMap

• A SortedSet maintains its elements in ascending order
– Additional operations are provided to take advantage of the ordering
– SortedSet is implemented by TreeSet
• SortedMap is the Map analog of SortedSet. The mappings are maintained in ascending key order (the key set is a sorted set)
– SortedMap is implemented by TreeMap
• For both, the sorted order is either determined by Comparable elements or by a Comparator provided at instantiation
·SortedSet按升序维护其元素

  • 提供额外的操作以利用排序
  • SortedSet由TreeSet实现
    · SortedMap是SortedSet的Map类似物。映射以键的升序进行维护(键集是一个排序集)
  • SortedMap由TreeMap实现
    ·对于两者,排序顺序由Comparable元素或在实例化时提供的Comparator确定

2.5 Factory methods and singleton

Factory Methods

• It creates objects of some type without the user necessarily specifying the concrete implementation of the type
• Users do not use the object’s constructor (The user does not use the new keyword)
• Access to constructors is often forbidden
• The factory pprovides static factory method(s) e.g. getInstance that can return an interface type
– “hiding” implementation detail
– The factory determines which implementation to use
– The choice of implementation can be deferred to run-time
• The factory can impose invariants such as uniqueness
• Polymorphism + interfaces + factories = implementation Independence
·它创建某种类型的对象,而无需用户指定该类型的具体实现
·用户不使用对象的构造函数(用户不使用new关键字)
·经常禁止构造器
·工厂提供静态工厂方法,例如可以返回接口类型的getInstance

  • “隐藏”实施细节
  • 工厂决定使用哪个实现
  • 实现的选择可以推迟到运行时
    ·工厂可以强加不变量,例如唯一性
    多态+接口+工厂=实现独立性
    在这里插入图片描述在这里插入图片描述在这里插入图片描述• AccountFactory instantiates an account
    – Determines which account type from the key passed to getInstance
    Account acc = AccountFactory.getInstance(“free”, 1234);
    – Could be FreeAccount, OverdraftAccount or another implementation
    – Potential to configure an application to use different concrete implementations at run-time
    · AccountFactory实例化帐户
  • 从传递给getInstance的键中确定哪个帐户类型
    account = accountFactory.getInstance(“free”,1234);
  • 可以是FreeAccount、OverdraftAccount或其他实现
  • 配置应用程序以在运行时使用不同具体实现的可能性

在这里插入图片描述

Collections framework factory methods and wrappers

• Can use factory to create unmodifiable collections. Returns an unmodifiable collection for a given modifiable collection
• The Collections factory class gives you several static methods to create immutable wrappers for your collections or maps. All these methods starts with unmodifiable, followed by the name of the type of your structure
·可以使用工厂创建不可修改的集合。返回给定的可修改集合的不可修改集合
Collections工厂类为您提供了几个静态方法来为您的集合或映射创建不可变的包装器。所有这些方法都以unmodifiable开头,后跟结构类型的名称

public class Collections {
public static Collection unmodifiableCollection(Collection c) {…}
public static List unmodifiableList(List l) {…}
public static <K, V> Map<K, V> unmodifiableMap(Map<K, V> m) {…}
public static Set unmodifiableSet(Set s) {…}
public static SortedSet unmodifiableSortedSet(SortedSet s) {…}
public static <K, V> SortedMap<K,V> unmodifiableSortedMap(SortedMap <K, V>
s) {…}

}
在这里插入图片描述

Advantages of static factory methods

Advantages compared to constructors:

  1. Static factory methods can have more meaningful names
  2. Static factory methods are not required to create a new object each time they are invoked
    – Instances can be cached, can enforce other constraints
  3. Static factory methods can return an object of any subtype of their return type
    – The return type of an instantiated object can be restricted to its interface
    – Implementation can be hidden and changed at run-time
    – Service provider frameworks can be extended with new implementations (see Java Cryptography libraries)
    • See Bloch-EJ Item 1

Disadvantages of static factory methods

(Possible) disadvantages compared to constructors:

  1. Classes without public or protected constructors cannot be subclassed
    – A blessing? See composition versus inheritance (part 2.6)
  2. Static factory methods are not readily distinguishable from other static methods(they deviate from the norm)
    – The Collections static factories are an example
    » There is a tension between meaningful names and conveying the message that objects are being created
    – In contrast, constructors standout in the API
  3. There is a necessary level of indirection

Static factory methods: summary

• Do not automatically provide public constructors simply because they are the norm
• For a given class, consider whether the advantages of static factory methods are significant
– If they are, then do not provide constructors and provide factory methods instead
– If they are not, or the advantages are not compelling, then prefer constructors because they are
the norm

Singleton Pattern

• A singleton is a class that is instantiated exactly once

  • A typical use is to represent a system component e.g. OS, FileSystem or some class that controls other components (e.g. Bank issuing Accounts).
    Another example is the screen on a phone
    • Two ways to implement singleton
    – With public final field
    – With static factory

code demo

public class HashSetDuplicateWordsExample {
public static void main(String[] args) {
// array of words
String[] words = “What, my name is. What, my name is, What, my name
is…”.split(" ");
// create sets
Set uniques = new HashSet<>();
Set duplicates = new HashSet<>();
// populate sets
for (String s : words) {
if (!uniques.add(s)) {
duplicates.add(s);
}
}
// print sets
System.out.println("Unique Words: " + uniques);
System.out.println("Duplicate Words: " + duplicates);
// remove all words that are found in duplicates
uniques.removeAll(duplicates);
// print sets
System.out.println("Unique Words: " + uniques);
System.out.println("Duplicate Words: " + duplicates);
}
}

public class RemoveDuplicates {
public static void main(String[] args) {
final String[] colours = { “red”, “blue”, “orange”, “pink”, “purple”,
“red”, “green”, “blue”, “red” };
final List colourList = Arrays.asList(colours);
System.out.println("Colours: " + colourList);
System.out.println("Colours without duplicates: " +
removeDuplicates(colourList));
System.out.println("Sorted colours without duplicates: " +
sortAndremoveDuplicates(colourList));
}
public static Collection removeDuplicates(Collection c) {
return new HashSet©;
}
public static Collection sortAndremoveDuplicates(Collection
c) {
return new TreeSet©;
}
}

public class HashMapIterator {
public static void main(String[] args) {
// create and populate map
Map<String, String> foo = new HashMap<>();
foo.put(“s1”, “James”);
foo.put(“s2”, “Jane”);
foo.put(“s3”, “Rich”);
foo.put(“s4”, “Becky”);
// using for loop and keySet
for (String id : foo.keySet()){
System.out.println("Key: " + id);
}
// using for loop and values
// CAUTION, order is not guaranteed to match KeySet
for (String name : foo.values()){
System.out.println("Value: " + name);
}
// using for loop and entrySet
for (Map.Entry<String, String> entry : foo.entrySet()) {
System.out.println("Key: " + entry.getKey() + " Value: " +
entry.getValue());
}
}
}

public class FrequencyCount {
public static void main(String args[]) {
//array of Words
String[] words = “My name is What? My name is Who? My name
is …”.split(" “);
Integer freq;
Map<String, Integer> wordMap = new HashMap<String, Integer>();
// Keys:the words
// Vals:their frequency
for (String word : words) {
// get value associated with key
// if it does not exist, default value = 0
freq = wordMap.getOrDefault(word,0);
freq++;
wordMap.put(word, freq);
}
System.out.print(wordMap.size());
System.out.println(” distinct words detected");
System.out.println(wordMap);
Map<String, Integer> sortedMap = new TreeMap<String, Integer>(wordMap);
System.out.println(“In Sorted Order:”);
System.out.println(sortedMap);
}
}

public final class Module implements Comparable {
public static final int MIN_MODULE_NUMBER = 1000;
public static final int PREFIX_LENGTH = 3;
private final String prefix;
private final int number;
private final int semester;
public Module(String prefix, int number, int semester) {
if (prefix.length() != PREFIX_LENGTH)
throw new IllegalArgumentException("prefix: " + prefix);
if (number < MIN_MODULE_NUMBER)
throw new IllegalArgumentException("number: " + number);
if (semester != 1 && semester != 2)
throw new IllegalArgumentException("semester: " + semester);
this.prefix = prefix;
this.number = number;
this.semester = semester;
}
public String getPrefix() {
return prefix;
}
public int getNumber() {
return number;
}
public int getSemester() {
return semester;
}
public int compareTo(Module module) {
final int pCmp = prefix.compareTo(module.prefix);//call compareTo in
string class
if (pCmp != 0)
return pCmp;
return number != module.number
? number - module.number
: semester - module.semester;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!(obj instanceof Module))
return false;
final Module module = (Module) obj;
//NB this is not consistent with compareTo

return prefix.equals(module.prefix) && number == module.number;
//This is consistent with compareTo
//return prefix.equals(module.prefix) && number == module.number &&
semester == module.semester ;
}
@Override
public int hashCode() {
int hc = 17;
hc = 37 * hc + prefix.hashCode();
hc = 37 * hc + number;
return hc;
}
public String toString() {
final StringBuilder sb = new StringBuilder(prefix);
sb.append(number).append(“-”).append(semester);
return sb.toString();
}
}

public class UseModule {
public static void main(String[] args) {
final Module[] modulesArray
= new Module[] {
new Module(“CSC”, 8005, 2),
new Module(“CSC”, 8002, 2),
new Module(“MAS”, 1006, 2),
new Module(“JPN”, 1004, 1),
new Module(“CSC”, 8005, 1),
new Module(“CSC”, 1014, 2),
new Module(“JPN”, 1004, 1)
};
System.out.println("direct module comparison: "

  • modulesArray[1].compareTo(modulesArray[0]));
    // unordered (HashSet), no duplicates (Set interface uses equals)
    final Set unsortedModulesSet = new HashSet();
    // ordered (TreeSet), duplicates (SortedSet interface uses compareTo)
    final SortedSet sortedModulesSet = new TreeSet();
    for (final Module m : modulesArray) {
    sortedModulesSet.add(m);
    unsortedModulesSet.add(m);
    }
    System.out.println("array of modules: "
  • Arrays.toString(modulesArray));
    System.out.println("sorted set of modules: "
  • sortedModulesSet);
    System.out.println("unsorted set of modules: "
  • unsortedModulesSet);
    }
    }

public class InconsistencyEqualsCompareTo {
public static void main(String[] args) {
Module module1 = new Module(“CSC”,8014,1);
Module module2 = new Module(“CSC”,8014,2);
Set set = new HashSet();
set.add(module1);
set.add(module2);
System.out.println("HashSet "+set);
Set treeSet = new TreeSet();
treeSet.add(module1);
treeSet.add(module2);
System.out.println("TreeSet "+treeSet);
}
}

public class StringSort implements Comparator {
public int compare(String s1, String s2) {
return s1.toLowerCase().compareTo(s2.toLowerCase());
}
public static void main(String args[]) {
String[] arr = { “one”, “two”, “three”, “four”, “Five”, “one”, “Ten” };
List list = Arrays.asList(arr);
Collections.sort(list); // default String sort
System.out.println(list);
// case independent String sort
Collections.sort(list, new StringSort());
System.out.println(list);
//String length sort
Collections.sort(list, new AnotherStringSort());
System.out.println(list);
}
}

public class AnotherStringSort implements Comparator{
public int compare(String s1, String s2) {
return s1.length() - s2.length();
}
}

public final class Name {
private static final Map<String, Name> NAMES = new HashMap<String, Name>();
private final String firstName, lastName, strRep;
private Name (String firstName, String lastName, String strRep) {
this.firstName= firstName;
this.lastName = lastName;
this.strRep = strRep;
}
public static Name getInstance (String firstName, String lastName) {
String strRep = firstName + " " + lastName;
Name name = NAMES.get(strRep);
if (name==null) {
name= new Name(firstName, lastName, strRep);
NAMES.put(strRep, name);
}
return name;
}
public String getFirstName() {return firstName;}
public String getlasstName() {return lastName;}
public String toString() {return strRep;}
}

ublic class UseName {
public static void main(String[] args) {
String fn1 = “John”;
String fn2 = “Smith”;
Name name1 = Name.getInstance(fn1,fn2);
Name name2 = Name.getInstance(“Jen”,“Jones”);
Name name3 = Name.getInstance(“John”,“Smith”);
System.out.println(“name1 same object as name2?” +(name1 == name2));
System.out.println(“name1 same object as name3?” +(name1 == name3));
}
}

public class UseAccountFactory {
public static void main(String[] args) {
System.out.println(“Using account factory”);
/*
// cannot create a FreeAccount directly because we’ve limited access (is
pkg-private)
//FreeAccount f = new FreeAccount(); // won’t work
// get free account with number 1234
final Account freeAccount1 =
AccountFactory.getInstance(AccountFactory.FREE_ACCOUNT, 1234);
// try to get another free account with number 1234.
// If factory imposes uniqueness this will be the same instance
final Account freeAccount2 =
AccountFactory.getInstance(AccountFactory.FREE_ACCOUNT, 1234);
// check that freeAccount1 == freeAccount2 - same instance
System.out.println("Only have single instance of freeAccount "

  • freeAccount1.getAccountNumber() + ": "
  • (freeAccount1 == freeAccount2));
    // freeAccount1 and freeAccount2 are same
    printAccountInfo(AccountFactory.FREE_ACCOUNT, freeAccount1);
    printAccountInfo(AccountFactory.FREE_ACCOUNT, freeAccount2);
    */
    // now we demo an overdraftAccount
    final Account overdraftAccount1 =
    AccountFactory.getInstance(AccountFactory.OVERDRAFT_ACCOUNT, 4567);
    printAccountInfo(“”, overdraftAccount1);
    final Account overdraftAccount2 =
    AccountFactory.getInstance(AccountFactory.OVERDRAFT_ACCOUNT, 5678);
    printAccountInfo(“”, overdraftAccount2);
    final Account overdraftAccount3 =
    AccountFactory.getInstance(AccountFactory.OVERDRAFT_ACCOUNT, 6789);
    printAccountInfo(“”, overdraftAccount3);
    final Account overdraftAccount4 =
    AccountFactory.getInstance(AccountFactory.OVERDRAFT_ACCOUNT, 7890);
    printAccountInfo(“”, overdraftAccount4);
    final Account overdraftAccount5 =
    AccountFactory.getInstance(AccountFactory.OVERDRAFT_ACCOUNT, 8901);
    printAccountInfo(“”, overdraftAccount5);
    }
    private static void printAccountInfo(String accType, Account account) {
    System.out.println(accType + " " + account + " is implemented by: " +
    account.getClass());
    }
    }

public interface Account {
void deposit(int amount);
int getAccountNumber();
int getBalance();
void transferBalance(Account acc);
int withdraw(int amount);
}

// abstract class providing partial implementation of Account
public abstract class AccountFactory implements Account {
public static final String FREE_ACCOUNT = “free”;
public static final String OVERDRAFT_ACCOUNT = “overdraft”;
// map of account number to instantiated account
// note static, so per-class map
private static final Map<Integer, Account> accounts = new HashMap<Integer,
Account>();
private final int accountNumber;
private int balance;
private static int nbOverdraft = 0;
AccountFactory(int accountNumber) {
this.accountNumber = accountNumber;
}
/**

  • Return an account of the specified type with the specified
  • account number.
  • @param account the type of account to return
  • @param accountNumber the account number
  • @return an account of the specified type. An existing account
  • is returned if accountNumber is already known. Otherwise
  • a new account with the given number is returned.
  • @throws NullPointerException if accountType is null
  • @throws IllegalArgumentException if accountType is an
  • invalid accounttype
    */
    public static Account getInstance(String account, int accountNumber) {
    // enforce single instance per accountNumber
    Account acc = accounts.get(accountNumber);
    if (acc != null) // impose uniqueness
    return acc;
    if (account.equals(FREE_ACCOUNT)) {
    acc = new FreeAccount(accountNumber);
    } else if (account.equals(OVERDRAFT_ACCOUNT)) {
    if (nbOverdraft < 3) {
    acc = new OverdraftAccount(accountNumber);
    nbOverdraft=nbOverdraft+1;
    }else {
    acc = new FreeAccount(accountNumber);
    }
    } else {
    throw new IllegalArgumentException("invalid account type: " + account);
    }
    // put acc in accounts map
    accounts.put(accountNumber, acc);
    // return the instance
    return acc;
    }
    public void deposit(int amount) {
    if (amount < 0)
    throw new IllegalArgumentException("Negative deposit: " + amount);
    balance = balance + amount;
    }
    public int getAccountNumber() {
    return accountNumber;
    }
    public int getBalance() {
    return balance;
    }
    public void transferBalance(Account acc) {
    final int accBalance = acc.getBalance();
    if (accBalance < 0)
    throw new IllegalArgumentException("Transfer from overdrawn account not
    allowed: " + acc);
    deposit(acc.withdraw(accBalance));
    }
    public String toString() {
    return "account number: " + accountNumber + " (balance: " + balance + “)”;
    }
    // utility method to allow subclasses to set the account balance
    void setBalance(int balance) {
    this.balance = balance;
    }
    }

/**

  • OverdraftAccount - bank account that allows overdrafts that
  • incur a charge. This OverdraftAccount can only be instantiated
  • by classes in this same package.
  • Use AccountFactory.getInstance(“overdraft”) to get an instance.

/
// package-private class definition
// - cannot be imported to other packages
final class OverdraftAccount extends AccountFactory {
private final static int OVERDRAFT_CHARGE = 10;
// package-private constructor cannot be directly instantiated by
// clients outside this package.
// Use AccountFactory.getInstance(“overdraft”) instead.
OverdraftAccount(int accountNumber) {
super(accountNumber);
}
/
*

  • Withdraw allows accounts to go into to the red and imposes
  • a fixed charge for withdrawals from overdrawn accounts.
  • @see uk.ac.ncl.teach.ex.factory.acc.Account#withdraw(int)
    */
    public int withdraw(int amount) {
    if (amount < 0)
    throw new IllegalArgumentException("Negative withdrawal: " + amount);
    final int newBalance = getBalance() - amount;
    if (newBalance < 0) {
    setBalance(newBalance - OVERDRAFT_CHARGE);
    } else {
    setBalance(newBalance);
    }
    return amount;
    }
    }

/**

  • FreeAccount - bank account with no overdraft and no charges.
  • This FreeAccount can only be instantiated by classes in
  • this same package. Use the AccountFactory.getInstance(“free”)
  • to get an instance.

/
// package-private class definition
// - cannot be imported to other packages
final class FreeAccount extends AccountFactory {
// package-private constructor cannot be directly instantiated by
// clients outside this package.
// Use AccountFactory.getInstance(“free”) instead.
FreeAccount(int accountNumber) {
super(accountNumber);
}
/
*

  • A withdrawal that puts the account into the red will not
  • be permitted.
  • @see uk.ac.ncl.teach.ex.factory.acc.Account#withdraw(int)
    */
    public int withdraw(int amount) {
    if (amount < 0)
    throw new IllegalArgumentException("Negative withdrawal: " + amount);
    final int currentBalance = getBalance();
    if (currentBalance < amount)
    return 0;
    setBalance(currentBalance - amount);
    return amount;
    }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/680641.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(三十五)大数据实战——Superset可视化平台搭建

前言 本节内容是关于Apache Superset可视化平台的搭建&#xff0c;Apache Superset是一个现代的数据探索和可视化平台 。它功能强大且十分易用&#xff0c;可对接各种数据源&#xff0c;包括很多现代的大数据分析引擎&#xff0c;拥有丰富的图表展示形式&#xff0c;并且支持自…

fatal error: rtiostream_utils.h: No such file or directory, rtiostream.h

fatal error: rtiostream_utils.h: No such file or directory 我的设置&#xff1a;

C++ //练习 6.23 参考本节介绍的几个print函数,根据理解编写你自己的版本。依次调用每个函数使其输入下面定义的i和j

C Primer&#xff08;第5版&#xff09; 练习 6.23 练习 6.23 参考本节介绍的几个print函数&#xff0c;根据理解编写你自己的版本。依次调用每个函数使其输入下面定义的i和j&#xff1a; int i 0, j[2] {0, 1};环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff…

UE5 播放本地MP3、MP4

1.创建一个媒体播放器 2.如创建视频&#xff0c;勾选。 它会多一个媒体纹理给你 3.1 设置音频 在一个actor上添加“媒体音频组件” “音频媒体播放器”赋值给它 3.2播放音频 添加一个音频媒体播放器变量&#xff0c; 赋值 地址使用绝对地址 4.1设置视频 UI上创建一个imag…

Redis -- 安装客户端redis-plus-plus

目录 访问reids客户端github链接 安装git 如何安装&#xff1f; 下载/编译、安装客户端 安装过程中可能遇到的问题 访问reids客户端github链接 GitHub - sewenew/redis-plus-plus: Redis client written in CRedis client written in C. Contribute to sewenew/redis-p…

【算法设计与分析】有效的字母异位词

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;算法分析与设计 ⛺️稳中求进&#xff0c;晒太阳 题目 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 注意&#xff1a;若 s 和 t 中每个字符出现的次…

适配器模式:接口转换的艺术,让不匹配成为过去式

适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;它通过将一个类的接口转换成客户期望的另一个接口&#xff0c;使得原本接口不兼容的类可以一起工作。在Java中&#xff0c;适配器模式可以通过实现一个适配器类来实现两个不兼容接口之间的转…

【Linux进阶之路】网络——“?“(上)

文章目录 一、历史发展1. 独立形态2. 互联形态3. 局域网 二、网络协议1.OSI七层协议2.TCP/IP四&#xff08;五&#xff09;层模型 三、网络通信1.封装与解包2.数据的传输1.局域网2.广域网 总结尾序 本篇文章的目的是带大家初步认识网络&#xff0c;为后面的网络编程打下基础&am…

原神4.0.1单机版【开局满级】纯单机,无限原石材料

版本介绍 版本4.0.1稳定版【过分追新并不稳&#xff0c;合理才完美】 独家原神&#xff0c;游戏内自带剧情任务&#xff0c;完美仿官&#xff0c;一比一完美复制&#xff01; 已经拥有完美剧情、任务、副本、卡池、深渊、全物品、和全部功能和皮肤。 修改注意 如果要进行不…

Swift Combine 有序的异步操作 从入门到精通十二

Combine 系列 Swift Combine 从入门到精通一Swift Combine 发布者订阅者操作者 从入门到精通二Swift Combine 管道 从入门到精通三Swift Combine 发布者publisher的生命周期 从入门到精通四Swift Combine 操作符operations和Subjects发布者的生命周期 从入门到精通五Swift Com…

C++:类的继承和派生

2.1继承 继承是面向对象的主要特征&#xff08;此外还要封装和多态&#xff09;之一&#xff0c;它使得一个类从现有类中派生&#xff0c;而不必重新定义一个新类。继承的实质就是用已有的数据类型创建新的数据类型&#xff0c;并保存已有数据类型的特点&#xff0c;以旧类为基…

Python爬虫之Ajax数据爬取基本原理

前言 有时候我们在用 requests 抓取页面的时候&#xff0c;得到的结果可能和在浏览器中看到的不一样&#xff1a;在浏览器中可以看到正常显示的页面数据&#xff0c;但是使用 requests 得到的结果并没有。这是因为 requests 获取的都是原始的 HTML 文档&#xff0c;而浏览器中…

编译安装mysql指定版本 shell脚本

要使用Shell脚本编译安装指定版本的MySQL&#xff0c;你需要下载源代码并按照官方文档的指引进行编译和安装。以下是一个简化的示例&#xff0c;用于下载、解压、编译和安装指定版本的MySQL&#xff1a; #!/bin/bash yum install -y wget cmake gcc yum install -y bzip2 bzi…

春节过半,预定的计划还没有开始

春节前就立下雄心勃勃的计划&#xff0c;想利春节假期开始搭一个人脸通WEB管理软件。但眼看春节过半&#xff0c;自己还没有开始动手呦。哎&#xff0c;突然紧张起来了。初二初三身体都不太舒服&#xff0c;不知道是怎么回事就感冒了&#xff0c;今晚更是高烧39.5&#xff0c;感…

【后端高频面试题--Linux篇】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;后端高频面试题 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; 后端高频面试题--Linux篇 Windows和Linux的区别&#xff1f;Unix和Linux有什么区别&#xff1f…

2024春晚纸牌魔术原理----环形链表的约瑟夫问题

一.题目及剖析 https://www.nowcoder.com/practice/41c399fdb6004b31a6cbb047c641ed8a?tabnote 这道题涉及到数学原理,有一般公式,但我们先不用公式,看看如何用链表模拟出这一过程 二.思路引入 思路很简单,就试创建一个单向循环链表,然后模拟报数,删去对应的节点 三.代码引…

备战蓝桥杯---动态规划(入门1)

先补充一下背包问题&#xff1a; 于是&#xff0c;我们把每一组当成一个物品&#xff0c;f[k][v]表示前k组花费v的最大值。 转移方程还是max(f[k-1][v],f[k-1][v-c[i]]w[i]) 伪代码&#xff08;注意循环顺序&#xff09;&#xff1a; for 所有组&#xff1a; for vmax.....0…

python使用 sqlalchemy连接数据库帮助类

import mysql.connectorclass MySqlHelper(object):"""操作数据库帮助类"""def __init__(self):#self.host "localhost"#self.user "root"#self.password "xinshiyun123"#self.database "deliverunion_c…

GPT4:你是故意的吧!

请问下面选项中哪个是中文&#xff1f; A.Chinese B.英文 这是一个关于语言识别的问题。我们需要分析并确定所给选项中哪个表示中文。 对于选项A.Chinese&#xff1a;这个词本身表示“中文”或“中国的”。在多种语境中&#xff0c;它经常被用来指代中国的语言&#xff0c;即中…

VTK 三维场景的基本要素(相机) vtkCamera 相机的运动

相机的运动 当物体在处于静止位置时&#xff0c;相机可以在物体周围移动&#xff0c;摄取不同角度的图像 移动 移动分为相机的移动&#xff0c;和相机焦点的移动&#xff1b;移动改变了相机相对焦点的位置&#xff0c;离焦点更近或者更远&#xff1b;这样就会改变被渲染的物体…