无代写-INFO1113
时间:2022-11-22

FEIT EDUCATION
'6��.Q:�
22s2 - INFO1113 期末复习
Part 2
by
Shirley老师
Generics 泛型
泛型的目的是提供编译时类型安全检测, 将数据类型传给泛型方法。它的好处是可以
在同一个结构上使用不同的数据类型。
泛型的声明
所有泛型方法声明都有一个类型参数声明部分,例如,用于传递数据类型。
声明的位置在方法返回类型之前,例如:
public static void method(T input){
每一个类型参数声明部分包含一个或多个类型参数,例如不只是, 也可以是
里面的字符 T被称为 Type parameter类型参数. 这些参数会在编译时一一对应到在代码
中使用的位置.
这个字母可以是任何字母,但有一些约定俗成的习惯,例如:
如果只有一个 type parameter,一般用 T表示 type。
如果这个 type parameter用于合集里,则用 E来表示 Element。
如果有多个 type parameter, 想表达的是 Key与 Value,用 K和 V来表示,等等
泛型可以用于泛型方法和泛型类。
泛型方法
在以下这个例子里,返回值是 void. 这个类型参数需要写在返回值前面,此
时才可以在方法中使用泛型类型 T。
例子:在集合里找东西并打印。
public static void findAndPrintItem(T item, T[] stuff){
for (T t: stuff){
if (t.equals(item)){
System.out.println(t);
break;
}
}
System.out.println("Can't find it");
}
泛型类

泛型类的声明是在 class的名字后面加上类型参数
public class Node {
//key这个成员变量的类型为 T,T的类型由外部指定
private T key;
private Node next;
public Node(T key) { //泛型 Constructor, key的类型也为 T,T的类型由外部指定
this.key = key;
}
public T getKey() { //泛型方法 getKey的返回值类型为 T,T的类型由外部指定
return key;
}
public void setNext(Node next) {
this.next = next;
}
}
public class GenericLinkedList {
private Node head = null;
public void AddFront(Node front) {
front.setNext(this.head);
this.head = front;
}

public static void main(String[] args) {
var list = new GenericLinkedList();
list.AddFront(new Node(1));
System.out.println(list.head.getKey());
}
}
限制泛型的使用范围
public class LinkedList {
通过 LinkedList这个 class的
类只能是 ParentClass的子类。
但即使如此,在编译结束以后,每一个 class分别使用的类型都会确定下来。子类之间
也是不可以混用的。
比如即使我们规定 List, Car和 Truck都是 Vehicle的子类,声明的时
候确定了是 List, List的两个 list object,这两个 list之间也不能再互相加对
方的类。
泛型的限制
1. 不可以在 generics里使用 primitive type
一直以来我们都知道 collections(比如 arraylist,linkedlist,hashmap)里,只能用
reference type,例如大写的 Integer,但不可以用小写的 int。其原因是 Generics的
type parameter规定了这个输入的 type不可以是 primitive type。它可以是任何数据类
型,包括 object,array,interface,甚至是另一个 type variable。
2. 如果使用了泛型,就不能在方法内部 cast数据或者判断数据的类型。这个的原因
是 Java编译器会在编译的时候抹除所有的 generic parameter。不可以通过 instance of
来判断具体到底是哪一种数据被作为 parameter传进方法里了。
例如:
public static void example(List list) {
if (list instanceof ArrayList) { // compile-time error
// ...
}
}
这里就会出现 compile time error。
Final 真题
选择
Given the following definitions, which assignments are legal?

class Box{}
class SuperBox extends Box{}

I. Box b = new Box();
II. Box b = new SuperBox();
III Box b = new SuperBox();

(a) I, II, III
(b) II only
(c) I and III only
(d) I only

简答
Write a Map using two array lists that supports storing Generic team name and integer
score. It should support adding a generic name/score pair to the map, and get score given a
generic team name.

public class MyMap {
private ArrayList teamNames;
private ArrayList scores;

public MyMap() {
teamNames = new ArrayList<>();
scores = new ArrayList<>();
}

public void add(T name, Integer score) {
int index = this.teamNames.indexOf(name);
if (index == -1) {
this.teamNames.add(name);
this.scores.add(score);
} else {
int existingScore = this.scores.get(index);
this.scores.set(index, existingScore+score);
}
}

public Integer getScore(T name) {
int index = this.teamNames.indexOf(name);
if (index == -1) {
return null;
}
return this.scores.get(index);
}
}

Abstract class
Abstract class UML

Abstract class和 Abstract Method都需要是斜体
Abstract class 的使用场景
某个 class不应该被实例化(不应该有其 object, 只能作为其他 class的蓝本), 但需要参与
继承(有足够多的 property需要传递给 child class)
例如: Shape之于 Circle, Animal之于 Cat.
Abstract Class除了不能产生对象之外,其它 Class的功能依然存在, 例如 member
variable, 成员方法和构造方法的访问方式和普通类一样 (依旧可以有 constructor, 可以
让子类使用 super)
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用
Abstract Method
只有 Abstract class才能有 Abstract method. 其特征是有 abstract修饰词, 有 return type,
input type等等 signature, 但没有 method body, 需要留给 subclass来写.
Abstract class可以有 concrete method, 也可以没有任何 Abstract Method.
“抽象类不一定有抽象方法,有抽象方法的类一定是抽象类”
真题练习
选择题
1. What is a method's signature?
a. The signature of a method is the name of the method the type of its return value.
b. The signature of a method is the name of the method and the names of its parameters.
c. The signature of a method is the name of the method and the data types of its
parameters.
d. The signature of a method is the name of the method, its parameter list, and its
return type.
答案: c. 当我们决定 overloading/overriding的时候,signature主要看名字和 parameter
的数据类型. 不包括 return type.
Interface
Interface不是 class, 是 Java中另一种实现 OOP的机制.
当我看到某个 class implements某个 interface的时候, 就了解了这个 class一定有什么
method可被使用.

在 UML中, Interface通常用<< >>书名号修饰.
与 Abstract Class不同的是, 使用 Interface使用的是 implement关键字, 不是 extends.
Interface不能被实例化, 通常用于给 class定义行为:
Interface的方法都是 public的. 写出来就是为了子类去实现的.
Interface里也可以有 variable, 但一般来说都是 public static final的, 仅用于定义一些不
应被修改的常量.
常用的 Interface
Comparable
public interface Comparable {
/**
* ....
* @param o the object to be compared.
* @return a negative integer, zero, or a positive integer as this object
* is less than, equal to, or greater than the specified object.
* @throws NullPointerException if the specified object is null
* @throws ClassCastException if the specified object's type prevents it
* from being compared to this object.
*/
public int compareTo(T o);
}
Iterable & Iterator
如果要让一个 class可以用 for – each (像 ArrayList一样), 则需要实现 Iterable接口.
但若要实现 Iterable里需要的方法, 需要先创建一个自定义的 Iterator (实现一个 Iterator
接口)
/**
* Implementing this interface allows an object to be the target of the enhanced
* {@code for} statement (sometimes called the "for-each loop" statement).
* @param the type of elements returned by the iterator
*/
public interface Iterable {
Iterator iterator();
}
public interface Iterator {
/**
* Returns {@code true} if the iteration has more elements.
* (In other words, returns {@code true} if {@link #next} would
* return an element rather than throwing an exception.)
*
* @return {@code true} if the iteration has more elements
*/
boolean hasNext();

/**
* Returns the next element in the iteration.
*
* @return the next element in the iteration
* @throws NoSuchElementException if the iteration has no more elements
*/
E next();
}
与 Abstract class 的区别
相同之处: 无论 abstract class 还是 interface, child class/ implement这个 interface的 class
里 都要将规定的 abstract method /method signature实现
不同之处:
1. Interface没有 constructor
2. Interface里的方法都是只有 signature的(不需要写 abstract), 都是 public的.
3. 继承使用的 extends 全将 superclass的 member variable与方法都继承下来.
Interface里没有.
4. interface 是给一个 class 附加一些 额外的功能
5. 继承只能 extend 一个 class,而 implements 可以有好多 interface
在我们不确定是否应该用抽象类还是 Interface的时候, 思考这个问题: 是否符合 IS-A关
系. 总的来说, 尽量多使用 Interface 或是 Composition模式(class A里拥有一个 class B
object作为其 member), 少用继承, 因为其不灵活.
真题练习
简答题

Line 15的时候, list里有 [A, B, A, C, A, D, D]
Descending Iterator是按照逆序遍历的, 打印也是逆序.
所以输出是 DDACABA.
简答
如何去手动写一个上一题这样的 reverse iterator?
import java.util.Iterator;

public class Reverse implements Iterable {
int [] content;
public Reverse(int[] content){
this.content = content;
}

// Implement a reverse iterator.
@Override
public Iterator iterator() {
return new Iterator() {
int index = content.length - 1;
@Override
public boolean hasNext() {
return index != -1;
}

@Override
public Integer next() {
return content[index--];
}
};
}

public static void main(String[] args) {
int [] content = {1, 2, 3};
Reverse list = new Reverse(content);
for(int i: list){
System.out.println(i);
}
}
}

这个例子里我们用到了 anonymous class,等下会一起复习。
同理,我们也可以通过调整 hasNext 和 next里 index更新的方式来实现其他的遍历方
式,比如一次跳过两个内容,等。
Enum 枚举类型
Enum通常被用来描述事实上有限的几种选择情况.
enum CardType {
HEARTS,
SPADES,
CLUBS,
DIAMONDS
}
public abstract class Main{
public static void main(String[] args) {
System.out.println(CardType.CLUBS);
}
}
在使用的时候, 通常用 Enum.type这样的形式来访问. 打印的话会直接打印其 string.
除了这一最普遍常见的, 类似于 String一样的用法, 它也可以用于产生几个特定的
instance.
enum CardType{
HEARTS("Red"),
SPADES("Red"),
CLUBS("Black"),
DIAMONDS("Black");

private String color;
CardType(String color){
this.color = color;
}
public String getColor(){
return this.color;
}
}
需要注意的是, 给 enum赋值/使用 constructor的部分需要写在开头.
Enum通常会与 switch配合使用. 可读性与错误防范的层面上比单纯用 string好很多, 在
编程规范中会被着重推广使用.
Enum的比较直接用 == , 类似 Primitive type.
Enum的排序按照自带的 ordinal. 例如:
enum Direction {
RIGHT,
LEFT,
UP,
DOWN
}
System.out.println(Direction.RIGHT.ordinal()); // 0
System.out.println(Direction.DOWN.ordinal()); // 3
真题练习
选择题

例如: 每次打印 enum.values()出来的顺序是一样的吗?
enum Direction {
RIGHT,
LEFT,
UP,
DOWN
}
public class ClassA {
public static void main(String[] args) {
System.out.println(Arrays.toString(Direction.values()));
}
}
答案: 是的, 打印顺序就是你写下来的顺序.
Testing 测试
Assert断言 Java自带的 assert关键字是最基本的断言方法. 断言的目的一般是用于在
test里验证结果的正确性, 并非在代码逻辑里使用.
语法: assert [expression]
如果 boolean expression 为 true,无事发生
如果 boolean expression 为 false,AssertionError,程序停止.
int a = 1;
int b = 2;
assert a - b == 0;
System.out.println("Here");
最后一行不会执行, 因为在此之前会在第三行有一个 AssertionError
Precondition
泛指是一段程序里在执行某个重要段落之前, 需要检查某些条件是否已经满足.
比如, 检查某些 field是否不为 null. 一般不用 assert, 因为是检查条件. 常用于 public
method.
public void setRefreshRate(int rate) {
// Enforce specified precondition in public method
if (rate <= 0 || rate > MAX_REFRESH_RATE)
throw new IllegalArgumentException("Illegal rate: " + rate);

setRefreshInterval(1000/rate);
}

Postcondition
泛指是, 一段程序里在执行某个重要段落之前, 需要检查某些条件已经被逻辑所改变, 也
就是你关心的这段程序是否已经 done its job.
一般用 assert来实现, 使用较少.
测试术语
白盒测试White box testing: 测试者知道程序怎么写的. 我们大部分的测试属于此类, 因
为我们是写程序的人也是写测试的人.
黑盒测试 Black box testing: 测试者不知道程序内部, 只知道测试的输入和应该的输出 .
单元测试 Unit test: 狭义的说是测试独立的 function,要保证这个测试是单独孤立的。
如果用了外部的资源,比如其他 class, 或者数据库,它就不是一个单元测试.
回归测试 Regression testing: 在一部分程序被修改后需要再次进行测试,且保证之前通
过的 testcases 必须仍然通过
集成测试 Integration testing: 与 unit test对应, 在 unit test通过测试后, 多个功能组装在
一起还是能通过测试.
Junit annotation
@Test
这个方法是一个 test, 表示这是个 test method. 通常要求这个方法本身也以 test 开头
@Before
这个方法会在每个 test method之前执行, 一般是准备资源, set up网络连接, 等等.
@After
会在每个 test method之后执行, 一般是收尾工作, 检查 post condition, 例如清理文件, 检
查是否有一些不需要被 call的方法没有被 evoke, 等等.
JavaDoc
Javadoc是一种统一的对每个 class和 function写 documentation的方式,可以用指令生
成 documentation页面。
例如:
/**
* Given a target, a cat will attempt to pounce
* and attack it with its claws.
* If successful, this will return true, otherwise false
* @param t, A cat's enemy target
* @return success
*/
常用的几个 annotation是:
@param, 描述每一个 input的 parameter的类型和作用
@return, 描述返回值的类型和作用
@throws,可能会抛出什么异常
@deprecated, 是否这个 class会在以后的版本里被淘汰掉。
可以用 javadoc -d .java 这样的命令来生成 document页面。

Recursion 递归
函数自己 call自己, 当前层的结果等于下一层计算的结果加上一些改变
private static int recur(int n){
if (n <= 1){
return n;
}else{
return recur(n - 1) + 1;
}
}
public static void main(String[] args) {
int res = recur(5);
}
递归里, 不 call程序本身(递归)的段落叫做 base case.
发生递归的段落叫做 recursion case.
常见问题
会遇到 Stack Overflow Exception的原因:
1. 没有写 base case
2. 程序无法抵达 base case.
比如这样:
static int fib(int n) {
if (n == 0 || n == 1) {
return 1;
}
return fib(n - 1) + fib(n);
注意三个 fib call的都是 n – 这里会导致每一次 recursion都重复传入相同的 input。

选择题
1. Given the functions below, what is the sequence: f(1), f(2), f(3), f(4), ...
int f( int num ) {
if ( num <= 2 )
return num;
else
return num*g(num-1);
}
int g( int num ) {
if ( num <= 2 )
return num;
else
return (num-1)*f(num+1);
}

(a) 1,2,6,24,...
(b) This recursion is incorrect in some way.
(c) 1,2,3,6,...
(d) 1,2,6,16,...

这个 recursion是有错误的,因为 f 会 call g(num-1), 但 g会反过来 call f(num+1),如此
一来他们都到不了 base case。

2. Given the function below, what is the value of f( 8, 9 )?
private int f( int x, int y ) {
if( x == 0 ) {
return y;
} else {
return f( x - 1, y + 1 );
}
}

(a) 0
(b) 17
(c) This recursion is incorrect in some way.
(d) 72


3. Given the function below, what is the value of g( 3 )?
private int g( int num ) {
if( num <= 1 ) {
return 1;
} else {
return 3*g( num-1 ) + g( num-2 );
}
}



(a) This recursion is incorrect in some way.
(b) 43
(c) 4
(d) 13

Final 真题
其 他 真 题

1. 第五行 cache应该是 static,因为后面几个方法是 static的。
2. 19行方法没有 return type,应该在 static后面加个 long。
3. 31行 map的方法应该是 put。

Recursion 常见的数据结构: Node
List的每一个存储空间由更小的单元 Node组成,node之间用 next确定位置。
一旦断开某个 next的位置,这个位置之后的数据视作全部被删除。

public class Node {
// add your class variables here
private T item;
private Node next;

// add your constructors and methods here
public Node(T item, Node next) {
this.item = item;
this.next = next;
}
}

Recursion 常见的数据结构:Binary Tree 或者 U-ary Tree
TreeNode
这个是一个 Binary Tree
class TreeNode {
int data;
TreeNode left;
TreeNode right;
}
如果将 left或者 right的 reference设为 null,那么它对应的子树都会被全部抹去。
这是一个 Children数目不固定的 N-ary Tree的结构.
class TreeNode {
int data;
List children;
}

class TreeNode {
int data;
List children;
TreeNode parent;
}

常见题型
LinkedList 链表
如何用递归方法来找一个值为 X的 node是否存在?


// Node class
class Node {
int data;
Node next;
Node(int d) {
data = d;
next = null;
}
}

class LinkedList {
Node head;
public void push(int new_data) {
Node new_node = new Node(new_data);
//Make next of new node as head
new_node.next = head;
//Move the head to point to new Node
head = new_node;
}

public boolean search(Node head, int x) {
// Base case
if (head == null)
return false;
// return true if key is present in current node
if (head.data == x)
return true;
// Recurion for remaining list
return search(head.next, x);
}
}
Tree 树相关问题

如何在一个二叉树/搜索树中确认一个值是否存在?

class Node {
int data;
Node left;
Node right;
Node(int d) {
data = d;
}
}

class Tree {
Node root;
public boolean search(Node root, int x) {
// Base case
if (root == null)
return false;
// If key is present in current node, return true
if (root.data == x) {
return true;
// Recur for remaining list
} else if (root.data > x) {
return search(root.left, x);
} else {
return search(root.right, x);
}
}
}

enum NodeTypes {NUMBER, OPERATOR}
public class Node {
NodeTypes type; // which type of node is this?
double number; // the value in a node of type NUMBER.
char operator; // the operator in a node of type operator.
Node left;
Node right;

// constructor for node of type operator
Node(char operator, Node left, Node right) {
type = NodeTypes.OPERATOR;
this.operator = operator;
this.left = left;
this.right = right;
}

// constructor for creating a node of type number
Node(double number) {
type = NodeTypes.NUMBER;
this.number = number;
}

public static void main(String[] args) {
Node seven = new Node(7);
Node one = new Node(1);
Node plus = new Node('+', seven, one);
Node four = new Node(4);
Node division = new Node('/', plus, four);
Node three = new Node(3);
Node multiply = new Node('*', three, division);
Node seventeen = new Node(17);
Node five = new Node(5);
Node minus = new Node('-', seventeen, five);
Node root = new Node('+', multiply, minus);
// your method here.
double result = yourMethod(root);
System.out.println(result);
}
}


这是一个 PostOrder的树的算法.
我们需要先递归地算出子树的运算结果, 再应用 root的运算符进行计算.
public static double postOrder(Node root) {
if (root.type != NodeTypes.OPERATOR) {
// assumption: root.left == null && root.right == null
return root.number;
}
// assumption:
// In a valid tree all OPERATOR node should have exactly 2 children.
double leftNodeResult = postOrder(root.left);
double rightNodeResult = postOrder(root.right);
switch (root.operator) {
case '+':
return leftNodeResult + rightNodeResult;
case '-':
return leftNodeResult - rightNodeResult;
case '*':
return leftNodeResult * rightNodeResult;
case '/':
return leftNodeResult / rightNodeResult;
default:
throw new AssertionError("Should not have other operators");
}
}

例题:Palindrome

A palindrome is a word or phrase that reads the same forward or backwards. Write a
recursive method that returns a boolean value indicating if its only String argument is a
palindrome or not. The method must be recursive and have the following signature:

public static boolean isPalindrome( String arg )

In testing for palindrome you should ignore upper/lower case as well as whitespace. That is,
the following phrases should be legal palindromes.

No Sir prefer prison
Racecar
Straw Warts
never odd or even
Oozy rat in a sanitary zoo


Place the isPalindrome method in a class named Palindrome. Write a main method in
Palindrome which prompts for a string from the keyboard, test if it is a palindrome, and
print out the result. Below is a sample output.

The string: ’No Sir prefer prison’ is a palindrome
The string: ’Try this’ is NOT a palindrome


public boolean isPalindrome(String s) {
if (s.length() <= 1)
return true; // base case
else {
if (s.toLowerCase().charAt(0) ==
s.toLowerCase().charAt(s.length() - 1))
return isPalindrome(s.substring(1, s.length() - 1));
else
return false;
}
} // end isPalindrome()

Final 真题:Interface 与递归
1. Create an interface MyInterface which contains only one default method, int
CountNonZero(int n).
CountNonZero is a recursive method that returns the number of non-zero digits in a given
integer n.
For example, if n = 20203 then CountNonZero(n) should return 3.

Create an anstract class MyClass which implements MyInterface and contains an abstract
method double power(int n, int m). Use an anonymous class to implement this method so
that returns n^m. For example, if n = 5, m = 2, then power(n, m) should return 25.

In the driver program, print the value of these two methods for the example data.

public abstract class MyClass implements MyInterface {
public abstract double power(int n, int m);

public static void main(String[] args) {
MyClass test = new MyClass() {
@Override
public double power(int n, int m) {
return Math.pow(n, m);
}

@Override
public int CountNonZero(int n) {
if (n == 0)
return 0;
if (n % 10 == 0)
return CountNonZero(n / 10);
else
return 1 + CountNonZero(n / 10);
}
};
System.out.println(test.power(5, 2));
System.out.println(test.CountNonZero(20203));
}
}


Inner class 内部类
Java 一个类中可以嵌套另外一个类, 写法如:
class OuterClass {
// ...
class InnerClass {
// ...
}
}
内部类经常用于执行 outer class里的逻辑. 这种情况下, inner class只在 outer class里作
为一种数据类型被使用.
例如一个 method的计算结果需要两个不同的 data type, 可以把数据并为一起返回.
public class OuterClass {
class InnerClass{
int numericResult;
String textResult;
public InnerClass(int n, String t){
this.numericResult = n;
this.textResult = t;
}
}
private InnerClass dummyCalculation(int param){
// ... some logic
return new InnerClass(1, "Dummy Value");
}
public int getNumericResult(){
// ...
InnerClass result = dummyCalculation(10);
return result.numericResult;
}
}
Public/Private inner class
Public inner class可以被外部访问
public class Main {
OuterClass out = new OuterClass();
OuterClass.InnerClass in = out.new InnerClass(1, "dummy");
Private inner class则不能从 Outer class外部被创建对象, 只能在 Outer class里面使用.
什么情况下使用 private class?
在内部类不想轻易被任何人访问,实现封装. 多数情况下在刚刚举例的使用场景里
inner class应当是 private的
Static/Non- static class
如果 Inner前面没有 static, 要从外部创建 Inner对象, 则需要先创建一个 Outer object. 因
为 Non static class是依赖于 object的.
public class Main {
OuterClass out = new OuterClass();
OuterClass.InnerClass in = out.new InnerClass(1, "dummy");
}
但如果 Inner是一个 static class, 从外部创建 inner对象可以直接通过 Outer class类.
public class Main {
OuterClass.InnerClass in = new OuterClass.InnerClass(1, "dummy");
}
内部类的 Scope
内部类的 parameter可以直接访问外部类的 parameter,包括 private parameter
但外部类如果要想访问内部类 parameter,则必须创建对象.
class Outer {
public int age = 18;
class Inner {
public int age = 20;
public void showAge() {
int age = 25;
System.out.println(age);// 25
System.out.println(this.age);// 20
System.out.println(Outer.this.age);// 18
}
}
public static void main(String[] args) {
Outer outer = new Outer();
Inner inner = outer.new Inner();
inner.showAge();
}
}
Anonymous class 匿名类
匿名类是内部类的一种简化写法. 常用的地方是用于实现函数需要的接口.
很多方法需要创建一个实现了接口的 class产生一个 object,但实际上无所谓这个 class
叫什么名字。例如 Comparator,我们只需要一个实现了 compare方法的 object,随便
叫什么都可以。
以下是一个 comparator的例子:
如果我们有一个 student的 array,student有一个年龄的 attribute,我们想要用
Arrays.sort对其进行按照年龄排序:
这里的 Arrays.sort要求一个 Comparator object,来提供按照给学生按照 Age排序。
void sort(T[] a, Comparator c) {
如果不用匿名类, 需要写一个额外的 class去实现 Comparator 接口,再实现 compare方
法. 而这里这个额外的 class不需要名字
例如:
public class AgeComparator implements Comparator {
@Override
public int compare(Student o1, Student o2) {
return o1.age - o2.age;
}
}

Arrays.sort(students, new AgeComparator());

但我们可以使用匿名类来省略新写一个 class,直接把方法实现在 new Compatator() {}里

public class TestComparator {
public static void main(String[] args) {
Student s1 = new Student(16, 'n', 99); //age, gender, grade
Student s2 = new Student(18, 'n', 98);
Student[] students = {s1, s2};
Arrays.sort(students, new Comparator() {
public int compare(Object o1, Object o2) {
Student s1 = (Student) o1;
Student s2 = (Student) o2;
return s1.age - s2.age;
}
});
}
Final 真题练习

答案: 2

Lambda 与 Stream

Stream 是一种用于加快计算的新语法. 它更像一个高级版本的 Iterator. 数据只能遍历
一次,遍历过一次后即用尽了. Stream不是一种 Collection,它不是数据结构, 不能用来
像 List/Map那样保存数据.

一般我们的 List,Set之类原本就是 iterator的 collection类型都可以通过.stream()转化
为 stream。

一些常见的例子:
List strings = new ArrayList<>();
strings.add("apple");
strings.add("beer");
strings.add("cafe");

// Sample 1:
// Filter strings contains 'a' using for loop:
List stringsWithA = new ArrayList<>();
for (String s : strings) {
if (s.contains("a")) {
stringsWithA.add(s);
}
}
// Filter strings contains 'a' using lambda:
List stringsWithALambda = strings.stream().filter(s ->
s.contains("a")).collect(Collectors.toList());

// Sample 2:
// Create list contains upper case using for loop:
List stringsToUpperCase = new ArrayList<>();
for (String s : strings) {
stringsToUpperCase.add(s.toUpperCase());
}
// Using lambda
List stringsToUpperCaseLambda = strings.stream().map(s ->
s.toUpperCase()).collect(Collectors.toList());

// Sample 3: Using lambda to combine two operations
List stringsWithAToUpperCase = strings.stream() //
.filter(s -> s.contains("a"))//
.map(s -> s.toUpperCase())
.collect(Collectors.toList());

Filter
Filter的作用是从 stream里筛选出符合一个 boolean的元素。见上面的第一个
example。
Map
Map的作用是输入一个 object并输出一个其他的 object.
例如: 输入是一个 string, 输出是它的 upper case
又例如: 输入是一个数字, 输出是这个值*3.
//odd values multiplied by 10 and displayed in a sorted order
IntStream.of(values)
.filter(x->x%2==1)
.map(x->x*10)
.sorted()
.forEach(x->System.out.printf("%d%n", x));

最常见的应用在于快速获取一些 object的 property, 例如:
List staff = Arrays.asList( new Staff("mkyong", 30), new Staff("jack", 27));

Quiz/Final 真题




public class ParentClass {
public String name;
public ParentClass(String name){
this.name = name;
}
}

public class Shop extends ParentClass {
LinkedList productsToSell;
public Shop(String name, LinkedList productToSell){
super(name);
this.productsToSell = productToSell;
}
public String getName(){
return super.name;
}
}

public class Customer extends ParentClass {
private LinkedList productsToBuy;

public Customer(String name, LinkedList productsToBuy) {
super(name);
this.productsToBuy = productsToBuy;
}

public Set shopToVisit(Shop[] shops) {
// set will remove duplicate.
Set toVisit = new HashSet<>();
for (String product : productsToBuy) {
for (Shop shop : shops) {
// Using lambda for filter.
if (shop.productsToSell.stream() //
.anyMatch(p -> p.toLowerCase().equals(product.toLowerCase())) //
) {
toVisit.add(shop.getName());
}
}
}
return toVisit;
}
}


学霸联盟
essay、essay代写