I have a table with 4 string columns in database, each row represent blocked user or group.
referrer | ip | userAgent | email
By group I mean that one of the columns (any) can have wild card (asterisk) which mean "block all of them"
for example this row
www.google.com | 127.0.0.2 | * | yahoo.com
Means that each user request with "google.com" as referrer, "127.0.0.2" asIP & "yahoo.com" as email, need to be blocked without consider UserAgent because it has wild card
The following code works in O(n) complexity, which is good enough for a small size table but my table contains over million rows
class BlacklistEntry {
private String referrer, ip, userAgent, email;
private static List<BlacklistEntry> cache = new ArrayList<>();
BlacklistEntry(String referrer, String ip, String userAgent, String email) {
this.referrer = referrer;
this.ip = ip;
this.userAgent = userAgent;
this.email = email;
}
private static boolean isBlacklisted(String ref, String ip, String ue, String email) {
final String MATCH_ALL = "*";
return cache.stream()
.filter(e ->
(MATCH_ALL.equals(e.getReferrer()) || e.getReferrer().equals(ref)) &&
(MATCH_ALL.equals(e.getIp()) || e.getIp().equals(ip)) &&
(MATCH_ALL.equals(e.getUserAgent()) || e.getUserAgent().equals(ue)) &&
(MATCH_ALL.equals(e.getEmail()) || e.getEmail().equals(email)))
.findFirst()
.isPresent();
}
public String getReferrer() {
return referrer;
}
public void setReferrer(String referrer) {
this.referrer = referrer;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getUserAgent() {
return userAgent;
}
public void setUserAgent(String userAgent) {
this.userAgent = userAgent;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public static void main(String[] args) {
cache.add(new BlacklistEntry("google.com", "127.0.0.2", "Mozilla", "yahoo.com"));
cache.add(new BlacklistEntry("r1.com", "127.0.0.3", "Mozilla", "*"));
cache.add(new BlacklistEntry("r2.com", "127.0.0.4", "Mozilla", "yahoo.com"));
System.out.println(isBlacklisted("r2.com", "127.0.0.4", "Mozilla", "yahoo.com"));
System.out.println(isBlacklisted("r1.com", "127.0.0.3", "Mozilla", "sould be true"));
System.out.println(isBlacklisted("*", "127.0.0.3", "*", "*"));
}
}
Is there something better than O(n) ? should I consider using Lucene ?
equals()andhashCode()methods are both broken. Yourequalsmethod should check for the wildcard character on "this" as well and yourhashCode()method should react on the wildcards. Keep in mind that objects, which are equals, must return the same hashcode.