我無法讀取您的代碼,所以我開始編寫單元測試以查看它在做什麼;重構,因爲我去了。這是我登陸的地方。你應該可以從這裏拿走它。您必須將合併列表合併到最少數量的術語中。
我將您的q56
類改名爲PolynomialUtils
。我添加了一個toString()方法,因爲代碼重複是程序員可以做的最糟糕的事情。這是迄今爲止我所擁有的。
您的節點類:
package math.badpoly;
/**
* Node
* Created by eitanmayer
* Creation date 1/9/2016.
* @link https://stackoverflow.com/questions/34695272/nodet-with-objects/34695704#34695704
*/
public class Node<T> {
private T value;
private Node<T> next;
public Node(T value) {
this.value = value;
this.next = null;
}
public Node(T value, Node<T> next) {
this.value = value;
this.next = next;
}
public T getValue() {
return this.value;
}
public Node<T> getNext() {
return this.next;
}
public boolean hasNext() {
return (this.next != null);
}
public void setValue(T value) {
this.value = value;
}
public void setNext(Node<T> next) {
this.next = next;
}
@Override
public boolean equals(Object o) {
if (this == o) { return true; }
if (o == null || getClass() != o.getClass()) { return false; }
Node<?> node = (Node<?>) o;
if (!value.equals(node.value)) { return false; }
return next != null ? next.equals(node.next) : node.next == null;
}
@Override
public int hashCode() {
int result = value.hashCode();
result = 31 * result + (next != null ? next.hashCode() : 0);
return result;
}
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(this.value.toString());
if (this.next != null) {
builder.append(this.next.toString());
}
return builder.toString();
}
}
你多項式類:添加重命名爲新的方法PolynomialUtils
package math.badpoly;
/**
* Polynomial
* Created by eitanmayer
* Creation date 1/9/2016.
* @link https://stackoverflow.com/questions/34695272/nodet-with-objects/34695704#34695704
*/
public class Polynomial {
private int num1;
private int num2;
public Polynomial(int num1, int num2) {
this.num1 = num1;
this.num2 = num2;
}
public int getNum1() {
return this.num1;
}
public int getNum2() {
return this.num2;
}
public void setNum1(int num1) {
this.num1 = num1;
}
public void setNum2(int num2) {
this.num2 = num2;
}
@Override
public boolean equals(Object o) {
if (this == o) { return true; }
if (o == null || getClass() != o.getClass()) { return false; }
Polynomial that = (Polynomial) o;
if (num1 != that.num1) { return false; }
return num2 == that.num2;
}
@Override
public int hashCode() {
int result = num1;
result = 31 * result + num2;
return result;
}
@Override
public String toString() {
return "(" + num1 + "," + num2 + ")";
}
}
您的Q56類:
package math.badpoly;
/**
* Created by eitanmayer
* Creation date 1/9/2016.
* @link https://stackoverflow.com/questions/34695272/nodet-with-objects/34695704#34695704
*/
public class PolynomialUtils {
public static int max(Node<Polynomial> list1, Node<Polynomial> list2) {
return Math.max(maxExponent(list1), maxExponent(list2));
}
public static int maxExponent(Node<Polynomial> polynomial) {
int max = Integer.MIN_VALUE;
Node<Polynomial> node = polynomial;
while (node != null) {
int exponent = node.getValue().getNum2();
if (exponent > max) {
max = exponent;
}
node = node.getNext();
}
return max;
}
public static int length(Node<Polynomial> polynomial) {
int count = 0;
Node<Polynomial> node = polynomial;
while (node != null) {
++count;
node = node.getNext();
}
return count;
}
public static Node<Polynomial> found(Node<Polynomial> polynomial, int max) {
Node<Polynomial> found = null;
Node<Polynomial> node = polynomial;
while (node != null) {
if (node.getValue().getNum2() == max) {
found = node;
}
node = node.getNext();
}
return found;
}
public static Node<Polynomial> last(Node<Polynomial> polynomialNode) {
Node<Polynomial> last = polynomialNode;
Node<Polynomial> node = polynomialNode;
while (node != null) {
last = node;
node = node.getNext();
}
return last;
}
public static Node<Polynomial> merge(Node<Polynomial> list1, Node<Polynomial> list2) {
Node<Polynomial> merged = list1;
Node<Polynomial> last = PolynomialUtils.last(merged);
last.setNext(list2);
return merged;
}
public static Node<Polynomial> consolidate(Node<Polynomial> list) {
// TODO: I've left this for you.
return null;
}
public static Node<Polynomial> sum(Node<Polynomial> list1, Node<Polynomial> list2) {
Node<Polynomial> listSum = PolynomialUtils.merge(list1, list2);
return listSum;
}
public static void main(String[] args) {
Node<Polynomial> list1 =
new Node<Polynomial>(new Polynomial(11, 11),
new Node<Polynomial>(new Polynomial(3, 9),
new Node<Polynomial>(new Polynomial(4, 7),
new Node<Polynomial>(new Polynomial(20, 4),
new Node<Polynomial>(new Polynomial(1, 2))))));
System.out.println(list1);
Node<Polynomial> list2 =
new Node<Polynomial>(new Polynomial(8, 10),
new Node<Polynomial>(new Polynomial(6, 7),
new Node<Polynomial>(new Polynomial(4, 2),
new Node<Polynomial>(new Polynomial(16, 2)))));
System.out.println(list2);
Node<Polynomial> sum = sum(list1, list2);
System.out.println(sum);
}
}
我寫了JUnit測試的PolynomialUtils
等級:
package math.badpoly;
import org.junit.Assert;
import org.junit.Test;
/**
* Created by Michael
* Creation date 1/9/2016.
* @link https://stackoverflow.com/questions/34695272/nodet-with-objects/34695704#34695704
*/
public class PolynomialUtilsTest {
private Node<Polynomial> list1 = createTestPolynomial1();
private Node<Polynomial> list2 = createTestPolynomial2();
@Test
public void testMax() {
int expected = 11;
int actual = PolynomialUtils.max(this.list1, this.list2);
Assert.assertEquals(expected, actual);
}
@Test
public void testLength_List1() {
Assert.assertEquals(5, PolynomialUtils.length(this.list1));
}
@Test
public void testLast_List1() {
Node<Polynomial> expected = new Node<Polynomial>(new Polynomial(1, 2));
Assert.assertEquals(expected, PolynomialUtils.last(this.list1));
}
@Test
public void testLength_List2() {
Assert.assertEquals(4, PolynomialUtils.length(this.list2));
}
@Test
public void testLast_List2() {
Node<Polynomial> expected = new Node<Polynomial>(new Polynomial(16, 2));
Assert.assertEquals(expected, PolynomialUtils.last(this.list2));
}
@Test
public void testFound_Success() {
Node<Polynomial> expected = new Node<Polynomial>(new Polynomial(11, 11), null);
Node<Polynomial> actual = PolynomialUtils.found(this.list1, 11);
Assert.assertEquals(expected.getValue().getNum1(), actual.getValue().getNum1());
Assert.assertEquals(expected.getValue().getNum2(), actual.getValue().getNum2());
}
@Test
public void testMerge() {
Node<Polynomial> expected = createMergedTestPolynomial();
System.out.println(list1);
System.out.println(list2);
System.out.println(expected);
Assert.assertEquals(expected, PolynomialUtils.merge(this.list1, this.list2));
}
@Test
public void testToString() {
String expected = "(11,11)(3,9)(4,7)(20,4)(1,2)";
Assert.assertEquals(expected, this.list1.toString());
}
@Test
public void testSum() {
Node<Polynomial> expected = createSumPolynomial();
Node<Polynomial> x = createTestPolynomial1();
Node<Polynomial> y = createTestPolynomial2();
System.out.println(x);
System.out.println(y);
Assert.assertEquals(expected, PolynomialUtils.sum(x, y));
}
private Node<Polynomial> createTestPolynomial2() {
Node<Polynomial> list2 =
new Node<Polynomial>(new Polynomial(8, 10),
new Node<Polynomial>(new Polynomial(6, 7),
new Node<Polynomial>(new Polynomial(4, 2),
new Node<Polynomial>(new Polynomial(16, 2)))));
return list2;
}
private Node<Polynomial> createTestPolynomial1() {
Node<Polynomial> list1 =
new Node<Polynomial>(new Polynomial(11, 11),
new Node<Polynomial>(new Polynomial(3, 9),
new Node<Polynomial>(new Polynomial(4, 7),
new Node<Polynomial>(new Polynomial(20, 4),
new Node<Polynomial>(new Polynomial(1, 2))))));
return list1;
}
private Node<Polynomial> createMergedTestPolynomial() {
Node<Polynomial> mergedList =
new Node<Polynomial>(new Polynomial(11, 11),
new Node<Polynomial>(new Polynomial(3, 9),
new Node<Polynomial>(new Polynomial(4, 7),
new Node<Polynomial>(new Polynomial(20, 4),
new Node<Polynomial>(new Polynomial(1, 2),
new Node<Polynomial>(new Polynomial(8, 10),
new Node<Polynomial>(new Polynomial(6, 7),
new Node<Polynomial>(new Polynomial(4, 2),
new Node<Polynomial>(new Polynomial(16, 2))))))))));
return mergedList;
}
private Node<Polynomial> createSumPolynomial() {
Node<Polynomial> expectedSum =
new Node<Polynomial>(new Polynomial(11, 11),
new Node<Polynomial>(new Polynomial(8, 10),
new Node<Polynomial>(new Polynomial(3, 9),
new Node<Polynomial>(new Polynomial(10, 7),
new Node<Polynomial>(new Polynomial(20, 4),
new Node<Polynomial>(new Polynomial(21, 2)
))))));
return expectedSum;
}
}
測試通過。所有的條款都存在於總和中。您必須像指數術語一樣整合。
我不打算回答你的問題,但我會提出一些建議,如果你決定繼續作爲程序員,今天或明天可能會覺得有用。
- 較少寫下代碼。
- 作爲開發人員學習的關鍵技能之一是 調試。
- 閱讀Bob Martin的Clean Code。
- 瞭解Java語言編碼和 命名標準。你經常打破他們。它使您的代碼 難以閱讀。
- 看看JUnit - 如果你繼續作爲程序員,你會很高興你做到了。
我不認爲這個實現是最優的。通過混合行爲和列舉行爲一起引發了一個問題。如果您決定從鏈接列表中更改,則必須重寫該類。如果他們分開,我想你會有更好的時間。
我建議你從Monomial
類開始:它將封裝係數和指數作爲私有數據成員。我認爲在這個班上實施你需要的操作(例如增加,減少等)是明智的。在繼續之前,確保它們完美地工作。
一旦書面和100%測試,創建一個Polynomial
類。這將管理一系列Monomials。關鍵的想法是收集的選擇不應該束縛在Monomial
或Polynomial
類。你被要求使用鏈表。當你將來學習地圖和散列表時,你可能會認爲從鏈表改變是一個好主意。那天你不應該重寫Monomial
或Polynomial
。
如果我這樣做我會用一個接口開始,無論Monomial
和Polynomial
可以實現:
package math.polynomial;
/**
* Interface for simple math operations
* Created by Michael
* Creation date 1/9/2016.
* @link https://stackoverflow.com/questions/34695272/nodet-with-objects/34695704#34695704
*/
public interface SimpleMath <T> {
T add(T other);
T sub(T other);
T mul(T other);
T div(T divisor);
T pow(int power);
T differentiate();
T integrate();
}
我想我的代碼執行Monomial
:
package math.polynomial;
/**
* Monomial class for polynomial
* Created by Michael
* Creation date 1/9/2016.
* @link https://stackoverflow.com/questions/34695272/nodet-with-objects
*/
public class Monomial implements SimpleMath<Monomial> {
/** Coefficients smaller than this will be considered as zero. */
public static final double MIN_COEFF = 1.0E-4;
private double coeff;
private int expon;
public Monomial() {
this(0.0, 0);
}
public Monomial(double coeff) {
this(coeff, 0);
}
public Monomial(int expon) {
this(1.0, expon);
}
public Monomial(double coeff, int expon) {
this.coeff = coeff;
this.expon = expon;
}
public double getCoeff() {
return coeff;
}
public int getExpon() {
return expon;
}
public Monomial add(Monomial other) {
if (this.getExpon() != other.getExpon()) throw new ExponentMismatchException(this, other);
return new Monomial(this.getCoeff()+other.getCoeff(), this.getExpon());
}
public Monomial sub(Monomial other) {
if (this.getExpon() != other.getExpon()) throw new ExponentMismatchException(this, other);
return new Monomial(this.getCoeff()-other.getCoeff(), this.getExpon());
}
public Monomial mul(Monomial other) {
return new Monomial(this.getCoeff()*other.getCoeff(), this.getExpon()+other.getExpon());
}
public Monomial div(Monomial other) {
return new Monomial(this.getCoeff()/other.getCoeff(), this.getExpon()-other.getExpon());
}
public Monomial pow(int power) {
return new Monomial(this.getCoeff(), this.getExpon()*power);
}
@Override
public Monomial differentiate() {
return (this.getExpon() == 0) ? new Monomial() : new Monomial(this.getCoeff()*this.getExpon(), this.getExpon()-1);
}
@Override
public Monomial integrate() {
return new Monomial(this.getCoeff()/(this.getExpon()+1), this.getExpon()+1);
}
@Override
public boolean equals(Object o) {
if (this == o) { return true; }
if (o == null || getClass() != o.getClass()) { return false; }
Monomial other = (Monomial) o;
return Double.compare(other.coeff, this.coeff) == 0 && this.expon == other.expon;
}
@Override
public int hashCode() {
int result;
long temp;
temp = Double.doubleToLongBits(coeff);
result = (int) (temp^(temp >>> 32));
result = 31 * result + expon;
return result;
}
@Override
public String toString() {
return String.format("(%.3f, %d)", this.getCoeff(), this.getExpon());
}
}
我倒是單元在進行前在其一英寸內測試它:
package math.polynomial;
import org.junit.Assert;
import org.junit.Test;
/**
* Junit tests for Monomial
* Created by Michael
* Creation date 1/9/2016.
* @link https://stackoverflow.com/questions/34695272/nodet-with-objects/34695704#34695704
*/
public class MonomialTest {
@Test
public void testContructor_Constant() {
double testCoeff = 2.0;
String testString = "(2.000, 0)";
Monomial monomial = new Monomial(testCoeff);
Assert.assertEquals(testCoeff, monomial.getCoeff(), Monomial.MIN_COEFF);
Assert.assertEquals(0, monomial.getExpon());
Assert.assertEquals(testString, monomial.toString());
}
@Test
public void testConstructor_UnitCoeff() {
int testExpon = 2;
String testString = "(1.000, 2)";
Monomial monomial = new Monomial(testExpon);
Assert.assertEquals(1.0, monomial.getCoeff(), Monomial.MIN_COEFF);
Assert.assertEquals(testExpon, monomial.getExpon());
Assert.assertEquals(testString, monomial.toString());
}
@Test
public void testConstructor() {
double testCoeff = 3.5;
int testExpon = 2;
String testString = "(3.500, 2)";
Monomial monomial = new Monomial(testCoeff, testExpon);
Assert.assertEquals(testCoeff, monomial.getCoeff(), Monomial.MIN_COEFF);
Assert.assertEquals(testExpon, monomial.getExpon());
Assert.assertEquals(testString, monomial.toString());
}
@Test
public void testAdd() {
Monomial x = new Monomial(3.0, 4);
Monomial y = new Monomial(4.0, 4);
Monomial expected = new Monomial(7.0, 4);
Assert.assertEquals(expected, x.add(y));
Assert.assertEquals(expected, y.add(x)); // Addition is commutative
}
@Test(expected = ExponentMismatchException.class)
public void testAdd_ExponentMismatch() {
Monomial x = new Monomial(3.0, 4);
Monomial y = new Monomial(4.0, 2);
x.add(y);
}
@Test
public void testAdd_Identity() {
Monomial x = new Monomial(3.0, 4);
Monomial y = new Monomial(0.0, x.getExpon());
Assert.assertEquals(x, x.add(y)); // Zero is the additive identity
Assert.assertEquals(x, y.add(x)); // Addition is commutative
}
@Test
public void testSub() {
Monomial x = new Monomial(3.0, 4);
Monomial y = new Monomial(4.0, 4);
Monomial expected = new Monomial(1.0, 4);
Assert.assertEquals(expected, y.sub(x));
expected = new Monomial(-1.0, 4);
Assert.assertEquals(expected, x.sub(y)); // Subtraction is not commutative
}
@Test(expected = ExponentMismatchException.class)
public void testSub_ExponentMismatch() {
Monomial x = new Monomial(3.0, 4);
Monomial y = new Monomial(4.0, 2);
x.sub(y);
}
@Test
public void testMul() {
Monomial x = new Monomial(3.0, 4);
Monomial y = new Monomial(4.0, 4);
Monomial expected = new Monomial(12.0, 8);
Assert.assertEquals(expected, x.mul(y));
Assert.assertEquals(expected, y.mul(x)); // Multiplication is commutative
}
@Test
public void testMul_Identity() {
Monomial x = new Monomial(3.0, 4);
Monomial y = new Monomial(1.0, 0);
Assert.assertEquals(x, x.mul(y));
Assert.assertEquals(x, y.mul(x)); // Multiplication is commutative
}
@Test
public void testDiv_ResultOne() {
Monomial x = new Monomial(3.0, 4);
Monomial expected = new Monomial(1.0, 0);
Assert.assertEquals(expected, x.div(x));
}
@Test
public void testDiv_ResultConstantTerm() {
Monomial x = new Monomial(3.0, 4);
Monomial y = new Monomial(4.0, 4);
Monomial expected = new Monomial(0.75, 0);
Assert.assertEquals(expected, x.div(y));
expected = new Monomial(4.0/3.0, 0);
Assert.assertEquals(expected, y.div(x)); // Division is not commutative
}
@Test
public void testDiv() {
Monomial x = new Monomial(2.0, 3);
Monomial y = new Monomial(4.0, 4);
Monomial expected = new Monomial(0.5, -1);
Assert.assertEquals(expected, x.div(y));
expected = new Monomial(2.0, 1);
Assert.assertEquals(expected, y.div(x)); // Division is not commutative
}
@Test
public void testDiv_Zero() {
Monomial x = new Monomial();
Monomial y = new Monomial(2.0, 3);
Monomial expected = new Monomial(0.0, -3);
Assert.assertEquals(expected, x.div(y));
expected = new Monomial(Double.POSITIVE_INFINITY, 3); // Note: No exception is thrown when dividing by 0.0
Assert.assertEquals(expected, y.div(x));
}
@Test
public void testPow() {
Monomial x = new Monomial(2.0, 3);
Monomial expected = new Monomial(2.0, 6);
Assert.assertEquals(expected, x.pow(2));
}
@Test
public void testPow_ZeroPower_Constant() {
Monomial x = new Monomial(2.0, 3);
Monomial expected = new Monomial(2.0, 0);
Assert.assertEquals(expected, x.pow(0));
}
@Test
public void testDifferentiate() {
Monomial x = new Monomial(2.0, 3);
Monomial expected = new Monomial(6.0, 2);
Assert.assertEquals(expected, x.differentiate());
}
@Test
public void testDifferentiate_Constant() {
Monomial x = new Monomial(4.0);
Assert.assertEquals(new Monomial(), x.differentiate());
}
@Test
public void testIntegrate() {
Monomial x = new Monomial(2.0, 3);
Monomial expected = new Monomial(0.5, 4);
Assert.assertEquals(expected, x.integrate());
}
@Test
public void testFundamentalTheoremOfCalculus() {
Monomial x = new Monomial(2.0, 3);
Assert.assertEquals(x, x.integrate().differentiate());
Assert.assertEquals(x, x.differentiate().integrate());
}
@Test
public void testEquals_Null() {
Monomial x = new Monomial(2.0, 3);
Assert.assertFalse(x.equals(null));
}
@Test
public void testEquals_Reflexive() {
Monomial x = new Monomial(2.0, 3);
Assert.assertTrue(x.equals(x));
}
@Test
public void testEquals_Symmetric() {
Monomial x = new Monomial(2.0, 3);
Monomial y = new Monomial(2.0, 3);
Assert.assertTrue(x.equals(y) && y.equals(x));
Assert.assertTrue(x.hashCode() == y.hashCode());
}
@Test
public void testEquals_Transitive() {
Monomial x = new Monomial(2.0, 3);
Monomial y = new Monomial(2.0, 3);
Monomial z = new Monomial(2.0, 3);
Assert.assertTrue(x.equals(y) && y.equals(z) && z.equals(x));
Assert.assertTrue(x.hashCode() == y.hashCode());
Assert.assertTrue(y.hashCode() == z.hashCode());
Assert.assertTrue(z.hashCode() == x.hashCode());
}
@Test
public void testEquals_DifferentCoefficients_NotEqual() {
Monomial x = new Monomial(2.0, 3);
Monomial y = new Monomial(1.0, 3);
Assert.assertFalse(x.equals(y));
Assert.assertFalse(y.equals(x));
Assert.assertFalse(x.hashCode() == y.hashCode());
}
@Test
public void testEquals_DifferentExponents_NotEqual() {
Monomial x = new Monomial(2.0, 3);
Monomial y = new Monomial(2.0, 4);
Assert.assertFalse(x.equals(y));
Assert.assertFalse(y.equals(x));
Assert.assertFalse(x.hashCode() == y.hashCode());
}
}
IntelliJ告訴我所有的測試都通過了。我有100%的方法測試覆蓋率和75%的線路覆蓋率。
現在,我有Monomial
完美工作,我會實施Polynomial
。它會使用相同的接口SimpleMath<Polynomial>
。它會選擇一些Monomial
的集合,這會使實現變得最簡單。在這裏你會發現你選擇的數據結構會讓你的生活變得更加困難或者更容易。好消息是,你可以在不打擾你的課程的客戶的情況下改變它,因爲這些實現細節將隱藏在你的課堂內部。
更新:
我完成了實施Polynomial
。這是驚人微妙。我很高興我有很好的Junit測試。根據測試結果演變而來的Monomial
和Polynomial
。
我不知道你是否注意到了,但他目前的Polynomial類實際上是你推薦的Mononomial。很難用名爲num1/num2的字段進行猜測。 – Aaron
我注意到了。這是我不喜歡的另一個混亂的位。好名字很重要。 – duffymo