希望有人能解释为什么我无法从HashSet
检索元素。
考虑我的HashSet
包含MyHashObjects
列表,其hashCode()
和equals()
方法已被正确覆盖。
我希望自己构建一个MyHashObject
,并将相关的哈希码属性设置为特定值。
我可以使用HashSet
方法查询contains()
以查看集合中是否存在“等效”对象。
因此,即使contains()
对于2个对象返回true,它们也可能不是==
。
为什么没有get()
方法类似于contains()
的工作原理?
有兴趣了解此API决定背后的想法
答案 0 :(得分:29)
如果您知道要检索的元素,那么您已经拥有了该元素。在给定元素的情况下,Set
唯一要回答的问题是contains()
是否{。}}。
如果要对元素进行迭代,只需使用Set.iterator()
。
听起来你要做的就是为元素的等价类指定一个规范元素。您可以使用Map<MyObject,MyObject>
执行此操作。有关讨论,请参阅this SO question或this one。
如果你真的决心找到一个.equals()
你的原始元素的元素,你必须使用HashSet
的约束,我想你一直在迭代它并检查{{1}你自己。 API不允许您通过其哈希码获取内容。所以你可以这样做:
equals()
蛮力和O(n)丑陋,但如果这是你需要做的......
答案 1 :(得分:10)
您可以HashMap<MyHashObject,MyHashObject>
代替HashSet<MyHashObject>
。
在您的“重建”ContainsKey()
上调用MyHashObject
将hashCode()
- 检查集合,如果重复哈希码被点击,最后equals()
- 检查您的“重建“使用get()
这是O(1),但缺点是您可能必须覆盖equals()
和hashCode()
方法。
答案 2 :(得分:7)
听起来你实际上是在尝试将哈希码用作地图中的键(这是HashSets在幕后所做的)。您可以通过声明HashMap<Integer, MyHashObject>
来明确地执行此操作。
HashSets没有get
,因为通常您将get
方法作为参数提供的对象与您将获得的对象相同。
答案 3 :(得分:4)
如果您知道设置中元素的顺序,则可以通过将设置转换为数组来检索它们。像这样:
Set mySet = MyStorageObject.getMyStringSet();
Object[] myArr = mySet.toArray();
String value1 = myArr[0].toString();
String value2 = myArr[1].toString();
答案 4 :(得分:1)
如果我在我的应用程序中确实知道该对象没有用于搜索任何列表或散列数据结构,并且除了在添加时间接在哈希数据结构中使用的方法之外,不使用equals方法。是否可以在equals方法中更新set中的现有对象。请参阅以下代码。如果我将这个bean添加到HashSet,我可以在key(id)上的匹配对象上进行组聚合。通过这种方式,我能够实现聚合函数,例如sum,max,min,....如果不可取,请随时与我分享您的想法。
package Part2;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.StringTokenizer;
public class Test {
public static void main(String[] args){
String inputFileName = "data.txt", input;
FileReader fileReader = null;
/**
* Create the FileReader
*/
try {
fileReader = new FileReader(inputFileName);
} catch (FileNotFoundException e) {e.printStackTrace();}
/**
* Use the BufferedReader class to read the data.txt file
*/
BufferedReader reader = new BufferedReader(fileReader);
/**
* Read the contents of the text file one line at a time using a loop
*/
try {
input = reader.readLine();
while (input != null)
{
/**
* Invoke processInputData method for each line read.
*/
processInputData(input);
input = reader.readLine();
}
} catch (IOException e) {e.printStackTrace();}
/**
* Close the input
*/
try {
fileReader.close();
} catch (IOException e) {e.printStackTrace();}
}//End of main method
/**
* Write a private method processInputData which processes its string
* input argument
*/
private static void processInputData(String data)
{
/**
* Tokenize the string argument using the StringTokenizer class
* using the comma as the delimiter.
*/
StringTokenizer st = new StringTokenizer(data,",");
/**
* Iterate over the tokens
*/
while (st.hasMoreTokens()){
/**
* Extract the name token. Create a Student object and assign
* to the variable currentStudent.
*/
String student = st.nextToken();
Student currentStudent = new Student(student);
/**
* Read each homework grade token one token at a time. Use
* the corresponding set method on the student object to set
* the instance value.
*/
int h1 = Integer.parseInt(st.nextToken());
currentStudent.setHomework1(h1);
int h2 = Integer.parseInt(st.nextToken());
currentStudent.setHomework2(h2);
int h3 = Integer.parseInt(st.nextToken());
currentStudent.setHomework3(h3);
int h4 = Integer.parseInt(st.nextToken());
currentStudent.setHomework4(h4);
int h5 = Integer.parseInt(st.nextToken());
currentStudent.setHomework5(h5);
int h6 = Integer.parseInt(st.nextToken());
currentStudent.setHomework6(h6);
/**
* Display the string representation of the currentStudent object
* to the console.
*/
System.out.println(currentStudent);
}
}
}
Error from Console:
java.io.FileNotFoundException: data.txt (The system cannot find the file specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(Unknown Source)
at java.io.FileInputStream.<init>(Unknown Source)
答案 5 :(得分:1)
您需要获取对Set对象中包含的对象的引用很常见。它可以通过两种方式存档:
根据需要使用HashSet,然后:
public Object getObjectReference(HashSet<Xobject> set, Xobject obj) {
if (set.contains(obj)) {
for (Xobject o : set) {
if (obj.equals(o))
return o;
}
}
return null;
}
要使这种方法起作用,您需要覆盖hashCode()和equals(Object o)方法 在最糟糕的情况下,我们有O(n)
第二种方法是使用TreeSet
public Object getObjectReference(TreeSet<Xobject> set, Xobject obj) {
if (set.contains(obj)) {
return set.floor(obj);
}
return null;
}
这种方法给出了O(log(n)),效率更高。 您不需要为此方法重写hashCode,但您必须实现Comparable接口。 (定义函数compareTo(Object o))。
答案 6 :(得分:0)
如果您可以使用List
作为数据结构来存储数据,而不是使用Map
将结果存储在Map的值中,则可以使用以下代码段并将结果存储在同一个对象。
以下是节点类:
private class Node {
public int row, col, distance;
public Node(int row, int col, int distance) {
this.row = row;
this.col = col;
this.distance = distance;
}
public boolean equals(Object o) {
return (o instanceof Node &&
row == ((Node) o).row &&
col == ((Node) o).col);
}
}
如果您将结果存储在距离变量中,并且根据坐标检查列表中的项目,则可以使用以下内容在 lastIndexOf 方法,只要您只需为每个数据存储一个元素:
List<Node> nodeList;
nodeList = new ArrayList<>(Arrays.asList(new Node(1, 2, 1), new Node(3, 4, 5)));
Node tempNode = new Node(1, 2, 10);
if(nodeList.contains(tempNode))
nodeList.get(nodeList.lastIndexOf(tempNode)).distance += tempNode.distance;
它基本上是重新实现Set
,其项目可以被访问和更改。
答案 7 :(得分:0)
首先将您的设置转换为Array。 然后,通过数组索引获取项目。
Set uniqueItem = new HashSet() ;
uniqueItem.add("0");
uniqueItem.add("1");
uniqueItem.add("0");
Object[] arrayItem = mySet.toArray();
for(int i = 0; i < uniqueItem.size();i++){
System.out.println("Item "+i+" "+arrayItem[i].toString());
}
答案 8 :(得分:0)
最简单的方法之一就是转换为数组:
for(int i = 0; i < set.size();i++){
System.out.println(set.toArray()[i]);
}
for(int i = 0; i < set.size();i++){
System.out.println(set.toArray()[i]);
}