[CS61B-Sp18] Exceptions, Iterations, Object Methods

这篇博客探讨了Java编程中的异常处理机制,详细介绍了迭代器的使用,包括增强型for循环的工作原理和手动实现。此外,还讨论了如何为自定义类实现Iterable接口,并给出ArraySetIterator类的例子。接着,文章深入讲解了对象方法,如toString()、equals(),并提供了优化toString()方法的建议。最后,提到了静态方法of()的用法及其在泛型编程中的应用。
摘要由CSDN通过智能技术生成

Exceptions, Iteratations, Object Methods

Exceptions

  • Syntax: throw new ExceptionObject(parameter1, ...)
    • example: throw new IllegalArgumentException("can't add null");

Iterations

Enhanced for loop

Set<String> s = new HashSet<>();
...
for (String city : s) {
    ...
}

translates to an ugly, manual approach:

Set<String> s = new HashSet<>();
...
Iterator<String> seer = s.iterator();
while (seer.hasNext()) {
    String city = seer.next();
    ...
}
  • Does the Set interface have an iterator() method? (1)
  • Does the Iterator interface have next/hasNext() methods? (2)

Implementation

Iterable: the interface making a class able to be iterated on, and requires the method iterator(), which returns an Iterator object. Think of any iterable as the object on which the iterator is performing.

Iterator: the interface defining the object with methods to actually do that iteration. Think of an Iterator as a machine that you put onto an iterable that facilitates the iteration.

(1) The Set interface extends the Iterable interface, inheriting the abstract iterator() method:

public interface Iterable<T> {
    Iterator<T> iterator();
}
public interface Set<T> extends Iterable<T>{
    ...
}

(2) The Iterator interface specifies abstract methods next() and hasNext():

public interface Iterator<T> {
    boolean hasNext();
    T next();
}

Example: iterable ArraySet class

Write a new class called ArraySetIterator, nested inside of ArraySet:

private class ArraySetIterator implements Iterator<T> {
    private int wizPos; // index to keep track of position in the array

    /* constructor */
    public ArraySetIterator() {
        wizPos = 0;
    }
    /* implement the abtract methods in Iterator interface */
    public boolean hasNext() {
        return wizPos < size;
    }
    public T next() {
        T returnItem = items[wizPos];
        wizPos += 1;
        return returnItem;
    }
}
  • Different objects need to be created for different structures like linked lists.

Need to make ArrayMap implement the Iterable interface. The essential method of the Iterable interface is iterator(), which returns an Iterator object for that class. We have to return an instance of our ArraySetIterator above:

public Iterator<T> iterator() {
    return new ArraySetIterator();
}

ArraySet code:

import java.util.Iterator;

public class ArraySet<T> implements Iterable<T> {
    private T[] items;
    private int size; // the next item to be added will be at position size

    public ArraySet() {
        items = (T[]) new Object[100];
        size = 0;
    }

    /* Returns true if this map contains a mapping for the specified key.
     */
    public boolean contains(T x) {
        for (int i = 0; i < size; i += 1) {
            if (items[i].equals(x)) {
                return true;
            }
        }
        return false;
    }

    /* Associates the specified value with the specified key in this map.
       Throws an IllegalArgumentException if the key is null. */
    public void add(T x) {
        if (x == null) {
            throw new IllegalArgumentException("can't add null");
        }
        if (contains(x)) {
            return;
        }
        items[size] = x;
        size += 1;
    }

    /* Returns the number of key-value mappings in this map. */
    public int size() {
        return size;
    }

    /** returns an iterator (a.k.a. seer) into ME */
    public Iterator<T> iterator() {
        return new ArraySetIterator();
    }

    private class ArraySetIterator implements Iterator<T> {
        private int wizPos;

        public ArraySetIterator() {
            wizPos = 0;
        }

        public boolean hasNext() {
            return wizPos < size;
        }

        public T next() {
            T returnItem = items[wizPos];
            wizPos += 1;
            return returnItem;
        }
    }

    public static void main(String[] args) {
        ArraySet<Integer> aset = new ArraySet<>();
        aset.add(5);
        aset.add(23);
        aset.add(42);

        //iteration
        for (int i : aset) {
            System.out.println(i);
        }
    }

}

Object Methods

toString()

  • The System.out.println() function implicitly calls toString()
  • The default Object class’s toString() method prints the address

Need to provide our own toString() method for our own classes:

  1. a less elegant solution that does string creations in a loop
@Override
public String toString() {
    String returnString = "{";
    for (int i = 0; i < size; i += 1) {
        returnString += keys[i];
        returnString += ", ";
    }
    returnString += "}";
    return returnString;
}
  1. a better solution that uses StringBuilder that creates a string object that is mutable, so you can continue appending instead of creating new ones.
@Override
public String toString() {
        StringBuilder returnSB = new StringBuilder("{");
        for (int i = 0; i < size - 1; i += 1) {
            returnSB.append(items[i].toString());
            returnSB.append(", ");
        }
        returnSB.append(items[size - 1]);
        returnSB.append("}");
        return returnSB.toString();
    }

equals()

  • == compares the bits of memory address and .equals() compares the content
  • By default, equals(Object o) acts like ==

Our own equals():

/* In order to override, must take Object as input. Potentially can compare to more general objects */
@Override
public boolean equals(Object other) {
        if (this == other) { // the memory addresses are the same (same object)
            return true;
        }
        if (other == null) { // null is always not equal to this
            return false;
        }
        if (other.getClass() != this.getClass()) { // if object of other type is compared to
            return false;
        }
        ArraySet<T> o = (ArraySet<T>) other;
        if (o.size() != this.size()) { // if size is different, not equal
            return false;
        }
        for (T item : this) {
            if (!o.contains(item)) { // final: if any content is different
                return false;
            }
        }
        return true;
    }

Rules for Equals in Java:

  • equals must be an equivalence relation:
    • reflexive: x.equals(x) is true
    • symmetric: x.equals(y) if and only if y.equals(x)
    • transitive: x.equals(y) and y.equals(z) implies x.equals(z)
  • It must take an Object argument, in order to override the original .equals() method
  • It must be consistent: if x.equals(y), then as long as x and y remain unchanged: x must continue to equal y
  • x.equals(null) must be false

Better toString()

String.join() takes in a String type delimiter and a iterable object and returns the string. List in this case, is iterable.

@Override
    public String toString() {
        List<String> listOfItems = new ArrayList<>();
        for (T x : this) {
            listOfItems.add(x.toString());
        }
        return "{" + String.join(", ", listOfItems) + "}";
    } 

of()

  • Static method does not get the type parameter, so need to make the method generic.
  • Glerp... stuff is called var arg
  • <Glerp> is the specified generic method type parameter
  • ArraySet<Glerp> is the return type
public static <Glerp> ArraySet<Glerp> of(Glerp... stuff) {
        ArraySet<Glerp> returnSet = new ArraySet<Glerp>();
        for (Glerp x : stuff) {
            returnSet.add(x);
        }
        return returnSet;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值