#2
wangyu442020-12-16 15:00
一个非常不错的问题。我来给你解释一下。
原因是你用了HashSet的add方法,add方法的源码如下: 程序代码: public boolean add(E e) { return map.put(e, PRESENT)==null; } 可以看到,实际hashset内部存值是用map(其实是hashmap)实现的,然后我们看一下hashmap的put方法源码(这里我直接也把put调用的putVal方法和hash方法给出来): 程序代码: static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); //这里调用了hashCode } public V put(K key, V value) { return putVal(hash(key), key, value, false, true); } final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node<K,V>[] tab; Node<K,V> p; int n, i; if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); else { Node<K,V> e; K k; if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) //这里调用了equals e = p; else if (p instanceof TreeNode) e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); else { for (int binCount = 0; ; ++binCount) { if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash); break; } if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; if (++size > threshold) resize(); afterNodeInsertion(evict); return null; } 可以看到put方法调用了hash(key)以及putVal(...)! 其中hash方法中当add的元素不为null时 会自动调用它的hashcode方法。 putVal方法会调用传入元素的equals方法。当然,因为hashmap的源码是很长的,putVal实现还是蛮复杂的,我只是这对其中一个else分支说的,不过其它的分支最终也是会调用equals方法。 [此贴子已经被作者于2020-12-16 15:04编辑过] |
程序代码:
import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;
public class Testa {
/*getSum方法 获得总额*/
public static double getSum(HashSet <Goods> goods) {
double sum=0;
double unitprice=0;
int quantity=0;
/*添加迭代器 获取每一个商品*/
Iterator<Goods> it=goods.iterator();
while(it.hasNext()) {
Goods x=new Goods();
x=it.next();
/*获取总额 商品单价*数量*/
sum+=(x.unitprice*x.quantity);
}
return sum;
}
public static void main(String[]ags) {
HashSet<Goods> gds=new HashSet<Goods>();
Scanner sc=new Scanner(System.in);
int i=0;
/*for循环 获得每一个商品对应的信息*/
for(i=0;i<5;i++) {
Goods goods=new Goods();
System.out.println("请输入商品的编号");
goods.number=sc.next();
System.out.println("请输入商品的名字");
goods.name=sc.next();
System.out.println("请输入商品的单价");
goods.unitprice=sc.nextDouble();
System.out.println("请输入商品的数量");
goods.quantity=sc.nextInt();
gds.add(goods); //!!!!!!!!!!!!!!!!
}
/*打印总额*/
System.out.println("您一共消费了"+getSum(gds)+"元!");
}
}
class Goods{
String number;
String name;
double unitprice;
int quantity;
//重写hashCode方法
public int hashCode() {
return number.hashCode();
}
//重写equals方法
public boolean equals(Object obj) {
if(this==obj)
return true;
if(!(obj instanceof Goods)) {
return false;
}
Goods goods=(Goods) obj;
boolean b=this.number.equals(goods.number);
/*如果相同 那么数量+1*/
if(b) {
goods.quantity++;
}
return b;
}
}
import java.util.Iterator;
import java.util.Scanner;
public class Testa {
/*getSum方法 获得总额*/
public static double getSum(HashSet <Goods> goods) {
double sum=0;
double unitprice=0;
int quantity=0;
/*添加迭代器 获取每一个商品*/
Iterator<Goods> it=goods.iterator();
while(it.hasNext()) {
Goods x=new Goods();
x=it.next();
/*获取总额 商品单价*数量*/
sum+=(x.unitprice*x.quantity);
}
return sum;
}
public static void main(String[]ags) {
HashSet<Goods> gds=new HashSet<Goods>();
Scanner sc=new Scanner(System.in);
int i=0;
/*for循环 获得每一个商品对应的信息*/
for(i=0;i<5;i++) {
Goods goods=new Goods();
System.out.println("请输入商品的编号");
goods.number=sc.next();
System.out.println("请输入商品的名字");
goods.name=sc.next();
System.out.println("请输入商品的单价");
goods.unitprice=sc.nextDouble();
System.out.println("请输入商品的数量");
goods.quantity=sc.nextInt();
gds.add(goods); //!!!!!!!!!!!!!!!!
}
/*打印总额*/
System.out.println("您一共消费了"+getSum(gds)+"元!");
}
}
class Goods{
String number;
String name;
double unitprice;
int quantity;
//重写hashCode方法
public int hashCode() {
return number.hashCode();
}
//重写equals方法
public boolean equals(Object obj) {
if(this==obj)
return true;
if(!(obj instanceof Goods)) {
return false;
}
Goods goods=(Goods) obj;
boolean b=this.number.equals(goods.number);
/*如果相同 那么数量+1*/
if(b) {
goods.quantity++;
}
return b;
}
}
用esclips逐句调试到!!!!!!标志的地方时 我发现hashCode 以及equals 方法是自动执行了 调用方法不是应该像good.hashCode(),good.equals(xxxx)这样吗?