我正在使用java 1.6。 我有一组项目,每个项目都有一个名称和一组组件。每个组件也有一个名称。
Set<Item>
Class Item
String name
Set<Component>
Class Component
String name
我现在的任务是编写一个带有输入的方法:项目名称+组件名称,输出:这一对是否存在于项目列表中。
public boolean hasItemComponentPair(String itemName, String componentName)
{
for(Item item : getItems())
{
if (item.getName() == itemName)
{
for(Component component : item.getComponents())
{
if (component.getName() == componentName)
{
return true;
}
}
}
}
return false;
}
最简单的方法是简单地逐个遍历集合的元素,如果找到匹配则中断。这种方法适用于小型集合。
我的项目集通常介于5到20个项目之间,组件集大致相同。因此,有25到400个独特的项目组件对。这对数量对于天真算法来说似乎太大了,特别是如果多次调用该方法。但我也认为,对于给定数量的元素,分而治之的技术过于冗长。
这个问题通常使用哪些数据结构和算法,请记住集合的大小?
答案 0 :(得分:3)
如果你可以改变你的Item类,你可以这样做:
class Item {
String name;
Map<String, Component> components;
}
在上面的地图中,key是组件的名称。
将代码更改为:
public boolean hasItemComponentPair(String itemName, String componentName)
{
for(Item item : getItems())
{
if (item.getName().equals(itemName))
{
return item.getComponents().containsKey(componentName);
}
}
return false;
}
现在您只需要遍历一个集合。
答案 1 :(得分:2)
1)对列表进行排序并对它们进行二进制搜索。
2)构建索引(通常作为哈希表)。
答案 2 :(得分:1)
覆盖Item和Component类中的equals和hashCode方法,如下所示:
// Item.java
import java.util.Set;
public class Item
{
private String name;
private Set<Component> components;
public Item(String name)
{
this.name = name;
}
@Override
public int hashCode()
{
return name.hashCode();
}
@Override
public boolean equals(Object obj)
{
if (obj instanceof Item)
{
Item item = (Item) obj;
if (item.name != null && this.name != null)
return item.name.equals(this.name);
}
return false;
}
public Set<Component> getComponents()
{
return components;
}
public void setComponents(Set<Component> components)
{
this.components = components;
}
}
// Component.java
public class Component
{
private String name;
public Component(String name)
{
this.name = name;
}
@Override
public int hashCode()
{
return name.hashCode();
}
@Override
public boolean equals(Object obj)
{
if (obj instanceof Component)
{
Component component = (Component) obj;
if (component.name != null && name != null)
return component.name.equals(this.name);
}
return false;
}
}
这将为您提供恒定的时间查找。因此,您可以在恒定时间内搜索元素。
以下是演示:
import java.util.HashSet;
public class SearchDemo
{
public static void main(String[] args)
{
Item item1 = new Item("Item 1");
item1.setComponents(new HashSet<Component>());
item1.getComponents().add(new Component("Component A"));
item1.getComponents().add(new Component("Component B"));
item1.getComponents().add(new Component("Component C"));
Item item2 = new Item("Item 2");
item2.setComponents(new HashSet<Component>());
item2.getComponents().add(new Component("Component X"));
item2.getComponents().add(new Component("Component Y"));
item2.getComponents().add(new Component("Component Z"));
HashSet<Item> items = new HashSet<>();
items.add(item1);
items.add(item2);
// Input from user
String inputItem = "Item 2";
String inputComponent = "Component Y";
// Cast it to item and component
Item searchItem = new Item(inputItem);
Component searchComponent = new Component(inputComponent);
if (items.contains(searchItem)) // Constant time search
{
System.out.println("Contains Item");
for (Item item : items)
{
if (item.equals(searchItem))
{
if (item.getComponents().contains(searchComponent)) // Constant time search
{
System.out.println("Contains even the component");
}
}
}
}
}
}
唯一的问题是上面查找中的for循环。
该项目可以在恒定时间内搜索,但必须在集合中再次搜索(如果它确实存在),因为我愚弄了程序,使其相信searchItem
等于item
在集合中。一旦找到该项并从中提取其组件集,就会对componentItem
进行恒定时间搜索。
如果HashMap
课程中有Component
Item
个Set
,而不是HashMap
,name
中的每个关键字都是component
{{1}}的{},然后可以在恒定时间内搜索用户的输入!