这段代码应该将两个方向的流量视为一个流程。 例如:
srcAddr,dstAddr,srcPort,dstPort
192.168.1.65, 217.174.16.1, 123456,80
应与
相同217.174.16.1, 192.168.1.65,80,123456
另一个例子:
192.168.1.65, 217.174.16.1, 12345, 80, TCP
217.174.16.1, 192.168.1.65, 80, 12345, TCP
192.168.1.65, 217.174.16.1, 12345, 80, TCP
217.174.16.1, 192.168.1.65, 80, 12345, TCP
我想保持这样:
Flow 1: key---> value (keeps statistics about each packet, like length and timeArrival)
[192.168.1.65, 217.174.16.1, 12345, 80] ----> [(outgoing, 1,2)(incoming,3,4)()()...]
192.168.1.65, 69.100.70.80, 98521, 80
69.100.70.80, 192.168.1.65, 80, 98521
192.168.1.65, 69.100.70.80, 98521, 80
69.100.70.80, 192.168.1.65, 80, 98521
192.168.1.65, 69.100.70.80, 98521, 80
69.100.70.80, 192.168.1.65, 80, 98521
Flow 2: [192.168.1.65, 69.100.70.80, 98521, 80] --> [(outgoing, 1,2)(incoming,3,4)()()...]
我应该如何改变才能获得结果? [即时通讯使用hashMap,这类Flow是我的关键]
package myclassifier;
public class Flows implements Comparable<Flows> {
String srcAddr = "", dstAddr = "", protocol = "";
int srcPort = 0, dstPort = 0;
public Flows(String sIP, String dIP, int sPort, int dPort){
this.srcAddr = sIP;
this.dstAddr = dIP;
this.srcPort = sPort;
this.dstPort = dPort;
//this.protocol = protocol;
}
public Flows(){
}
public int compareTo(Flows other) {
int res = 1;
if(this.equals(other)){
return res=0;
}else
return 1;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
result = prime * result + dstPort;
result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
result = prime * result + srcPort;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Flows other = (Flows) obj;
if (dstAddr == null) {
if (other.dstAddr != null)
return false;
} else if (!dstAddr.equals(other.dstAddr))
return false;
if (dstPort != other.dstPort)
return false;
if (srcAddr == null) {
if (other.srcAddr != null)
return false;
} else if (!srcAddr.equals(other.srcAddr))
return false;
if (srcPort != other.srcPort)
return false;
return true;
}
@Override
public String toString() {
return String.format("[%s, %s, %s, %s, %s]", srcAddr, dstAddr, srcPort, dstPort, protocol);
}
}
答案 0 :(得分:2)
最简洁的方法可能是定义这些方法:
Flows reverse()
返回给定Flows
的反方向Flows
Flows canon()
返回Flows
的规范化形式
Flows
srcAddr.compareTo(dstAddr) <= 0
是正典
reverse()
是正典然后,对于非定向比较,您可以简单地比较两个流的规范形式。使用这些方法可以使其余逻辑非常干净和可读(参见下面的代码)。
Comparator
,Comparable
上,与equals
使用上面的reverse()
概念,如果你总是希望f.equals(f.reverse())
,那么也许首先不应该有任何方向性的概念。如果是这种情况,那么规范化是最好的方法。
如果f
通常不是equals(f.reverse())
,但您可能希望f
和f.reverse()
与0进行比较,则不应使用Comparable
,因为这样做会强加一种与平等不一致的自然顺序。
来自文档:
当且仅当
C
具有与{{1}相同的布尔值时,类equals
的自然顺序被认为与e1.compareTo(e2) == 0
一致对于e1.equals(e2)
的每个e1
和e2
。强烈建议(尽管不是必需的)自然排序与
C
一致。
也就是说,不应在equals
中强加与Comparable
不一致的自然排序,而应改为提供非定向Comparator
。
作为类比,请将此情况与提供String
的Comparator<String> CASE_INSENSITIVE_ORDER
进行比较,该Java Tutorials/Collections/Object Ordering允许两个非equals
的字符串通过不区分大小写与0进行比较。
所以,在这里你写了一个equals
,它允许两个Comparator<Flows>
不是Flows
,通过方向不敏感来与0进行比较。
以下是具有equals
和Edge
的{{1}}类的示例实现,其方向自然顺序与from
一致,也提供了非to
-directional equals
。
然后使用3种Comparator
进行测试:
Set
,用于测试HashSet
和equals
hashCode
,用于测试自然排序TreeSet
的{{1}}来测试非方向性实施简洁明了,应具有指导意义。
TreeSet
输出为(Arrays.hashCode(Object[])
),注释:
Comparator
请注意,在非定向import java.util.*;
class Edge implements Comparable<Edge> {
final String from, to;
public Edge(String from, String to) {
this.from = from;
this.to = to;
}
@Override public String toString() {
return String.format("%s->%s", from, to);
}
public Edge reverse() {
return new Edge(to, from);
}
public Edge canon() {
return (from.compareTo(to) <= 0) ? this : this.reverse();
}
@Override public int hashCode() {
return Arrays.hashCode(new Object[] {
from, to
});
}
@Override public boolean equals(Object o) {
return (o instanceof Edge) && (this.compareTo((Edge) o) == 0);
}
@Override public int compareTo(Edge other) {
int v;
v = from.compareTo(other.from);
if (v != 0) return v;
v = to.compareTo(other.to);
if (v != 0) return v;
return 0;
}
public static Comparator<Edge> NON_DIRECTIONAL =
new Comparator<Edge>() {
@Override public int compare(Edge e1, Edge e2) {
return e1.canon().compareTo(e2.canon());
}
};
}
public class Main {
public static void main(String[] args) {
testWith(new HashSet<Edge>());
testWith(new TreeSet<Edge>());
testWith(new TreeSet<Edge>(Edge.NON_DIRECTIONAL));
}
public static void testWith(Set<Edge> set) {
set.clear();
set.add(new Edge("A", "B"));
set.add(new Edge("C", "D"));
System.out.println(set.contains(new Edge("A", "B")));
System.out.println(set.contains(new Edge("B", "A")));
System.out.println(set.contains(new Edge("X", "Y")));
System.out.println(set);
set.add(new Edge("B", "A"));
set.add(new Edge("Z", "A"));
System.out.println(set);
System.out.println();
}
}
中,// HashSet
// add(A->B), add(C->D)
true // has A->B?
false // has B->A?
false // has X->Y?
[C->D, A->B]
// add(B->A), add(Z->A)
[B->A, C->D, Z->A, A->B]
// TreeSet, natural ordering (directional)
// add(A->B), add(C->D)
true // has A->B?
false // has B->A?
false // has X->Y
[A->B, C->D]
// add(B->A), add(Z->A)
[A->B, B->A, C->D, Z->A]
// TreeSet, custom comparator (non-directional)
// add(A->B), add(C->D)
true // has A->B?
true // has B->A?
false // has X->Y?
[A->B, C->D]
// add(B->A), add(Z->A)
[A->B, Z->A, C->D]
被规范化为TreeSet
,这就是它按此顺序出现在Z->A
之前的原因。同样地,A->Z
被规范化为C->D
,这已经在集合中,这解释了为什么那里只有3 B->A
。
A->B
是不可变的Edge
一致,您可以在Edge
equals
compareTo == 0
中的多步equals
逻辑来简洁明了return
和compareTo
大大简化了无方向性比较
reverse()
canon()
equals
hashCode
equals
toString
注释答案 1 :(得分:0)
关键是要正确实现equals方法。在您的equals方法中,您返回false,目标地址不匹配。这是您需要添加其他逻辑以检查相等性的位置,因为您希望具有双向相等性。第一轮的平等应该是对源,目的地,港口的平等的检查。第二遍应该是源和目的地的反向相等。您还需要对默认值进行特殊设置,例如在您的示例中,将portno(80)的默认值排除为true。
答案 2 :(得分:0)
我不知道这是否会对你有所帮助。但它可以按照你说的方向工作
import java.util.HashSet;
public class Flows implements Comparable<Flows> {
String srcAddr = "", dstAddr = "", protocol = "";
int srcPort = 0, dstPort = 0;
public Flows(String sIP, String dIP, int sPort, int dPort){
this.srcAddr = sIP;
this.dstAddr = dIP;
this.srcPort = sPort;
this.dstPort = dPort;
//this.protocol = protocol;
}
public Flows(){
}
public int compareTo(Flows other) {
if(this.equals(other)){
return 0;
}else
return 1;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode())+((srcAddr == null) ? 0 : srcAddr.hashCode());
result = prime * result + dstPort+srcPort;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if(obj instanceof Flows)
{
Flows c=(Flows)obj;
if(srcAddr.equals(c.dstAddr) && dstAddr.equals(c.srcAddr) &&srcPort==c.dstPort && dstPort==c.srcPort)
return true;
if(srcAddr.equals(c.srcAddr) && dstAddr.equals(c.dstAddr) && srcPort==c.srcPort && dstPort==c.dstPort)
return true;
}
return false;
}
@Override
public String toString() {
return String.format("[%s, %s, %s, %s, %s]", srcAddr, dstAddr, srcPort, dstPort, protocol);
}
public static void main(String[] args) {
Flows f1=new Flows("192.168.1.65","217.174.16.1", 123456,80);
Flows f2=new Flows("217.174.16.1","192.168.1.65",80,123456);
Flows f3=new Flows("192.168.1.66","217.174.16.1", 123456,80);
Flows f4=new Flows("217.174.16.1","192.168.1.66",80, 123456);
System.out.println(f1.hashCode()+ " "+f2.hashCode());
HashSet<Flows> hh=new HashSet<Flows>();
hh.add(f1);
hh.add(f2);
hh.add(f3);
hh.add(f4);
System.out.println(f1.compareTo(f2));
System.out.println(hh);
}
}
我已经使用hashset来测试。所以它也适用于hashmap。