Add multiple fields to Java 5 HashSet at once? - java

Is there a better way to do this so I don't have to have 50 ".add()"s in there? Like a comma separated list or something (like JavaScript arrays).
private static final Set<String> validStates = new HashSet<String>();
validStates.add("AL");
validStates.add("AK");
validStates.add("AZ");
validStates.add("AR");
validStates.add("CA");
validStates.add("CO");
validStates.add("CT");
validStates.add("DE");
validStates.add("DC");
validStates.add("FL");
validStates.add("GA");
validStates.add("HI");
validStates.add("ID");
validStates.add("IL");
validStates.add("IN");
validStates.add("IA");
validStates.add("KS");
validStates.add("KY");
validStates.add("LA");
validStates.add("ME");
validStates.add("MD");
validStates.add("MA");
validStates.add("MI");
validStates.add("MN");
validStates.add("MS");
validStates.add("MO");
validStates.add("MT");
validStates.add("NE");
validStates.add("NV");
validStates.add("NH");
validStates.add("NJ");
validStates.add("NM");
validStates.add("NY");
validStates.add("NC");
validStates.add("ND");
validStates.add("OH");
validStates.add("OK");
validStates.add("OR");
validStates.add("PA");
validStates.add("RI");
validStates.add("SC");
validStates.add("SD");
validStates.add("TN");
validStates.add("TX");
validStates.add("UT");
validStates.add("VT");
validStates.add("VA");
validStates.add("WA");
validStates.add("WV");
validStates.add("WI");
validStates.add("WY");
Something like:
validStates.add("AL", "AK", "...");

The HashSet has a constructor taking a Collection. The Arrays#asList() takes arguments as varargs and returns a List (which is a Collection). So, you could do it as follows:
validStates = new HashSet<String>(Arrays.asList("AL", "AK", ".."));
It makes however more sense to have them in some properties file or in a DB which you load by one or two lines of code so that you don't need to hardcode them all in Java.
If you were on Java 8+, you could just use Stream#of().
validStates = Stream.of("AK", "AL", "..").collect(Collectors.toSet());

If you fancy using the excellent Google Guava library, you can use:
Set<String> validStates = Sets.newHashSet("AL", "AK", "...");

You could have a static String[] with all the states, then iterate over the array:
String states[] = {"AL","AK","AZ","AR",...etc...};
for (String currState : states) {
validStates.add(currState);
}
I don't remember if this "foreach" construct came in 1.5 or 1.6....

HashSet<String> hs = Sets.newHashSet("abc","xyz");

Related

Parsing String by pattern of substrings

I need to parse a formula and get all the variables that were used. The list of variables is available. For example, the formula looks like this:
String f = "(Min(trees, round(Apples1+Pears1,1)==1&&universe==big)*number";
I know that possible variables are:
String[] vars = {"trees","rivers","Apples1","Pears1","Apricots2","universe","galaxy","big","number"};
I need to get the following array:
String[] varsInF = {"trees", "Apples1","Pears1", "universe", "big","number"};
I believe that split method is good here but can’t figure the regexp required for this.
No need for any regex pattern - just check which item of the supported vars is contained in the given string:
List<String> varsInf = new ArrayList<>();
for(String var : vars)
if(f.contains(var))
varsInf.add(var);
Using Stream<> you can:
String[] varsInf = Arrays.stream(vars).filter(f::contains).toArray(String[]::new);
Assuming "variable" is represented by one alphanumeric character or sequential sequence of multiple such characters, you should split by not-alphanumeric characters, i. e. [^\w]+, then collect result by iteration or filter:
Set<String> varSet = new HashSet<>(Arrays.asList(vars));
List<String> result = new ArrayList<>();
for (String s : f.split("[^\\w]+")) {
if (varSet.contains(s)) {
result.add(s);
}
}

How to add list of items to an ArrayList<String> in java?

I have list of words which I need to load to ArrayList< String >
prefix.properties
vocab\: = http://myweb.in/myvocab#
hydra\: = http://www.w3.org/ns/hydra/core#
schema\: = http://schema.org/
"vocab:" is actually "vocab:" .Slash(\) is used to read colon(:) character because it is special character.
Dictionary.java
public class Dictionary {
public static ArrayList<String> prefix = new ArrayList<>();
static {
Properties properties = new Properties();
InputStream input = null;
input = ClassLoader.getSystemResourceAsStream("prefix.properties");
System.out.println(input!=null);
try {
properties.load(input);
} catch (IOException e) {
e.printStackTrace();
}
Set<Map.Entry<Object, Object>> entries = properties.entrySet();
for(Map.Entry<Object, Object> E : entries)
{
prefix.add(E.getKey().toString());
prefix.add(E.getValue().toString());
}
}
}
In Dictionary.java , ArrayList prefix will have
prefix = [
"vocab:",
"http://myweb.in/myvocab#",
"hydra:",
"http://www.w3.org/ns/hydra/core#",
"schema:",
"http://schema.org/"
]
I am querying some data in another class.
For eg:
public class QueryClass
{
public ArrayList<String> queryResult(String findKey)
{
ArrayList<String> result = new ArrayList<String>();
ArrayList<String> prefix = Dictionary.prefix;
Iterator<String> iterator = prefix.iterator();
while (iterator.hasNext())
{
String currentKey = iterator.next()+findKey;
/**
Here my logic to search data with this currentKey
*/
}
return result;
}
}
Problem :
I want to avoid this method to load from .properties file because there is possibility of odd number of elements can be present while .properties file provide (key,value) pair way to store data.
Reason why I have to load from separate file ? Because In future I will have to add more keywords/String thats why I put it in prefix.properties file.
Is there any alternative way to do this?
Do not re-invent the wheel.
If you can define the file format, then just go for java properties.
You see, the Properties class has a method getProperty(String, String) where the second argument can be used to pass a default value for example. That method could be used in order to fetch keys that don't come with values.
I would be really careful about inventing your own format; instead I would look into ways of re-using what is already there. Writing code is similar to building roads: people forget that each new road that is built translates to maintenance efforts in the future.
Besides: you add string values to a list of strings by calling list.add(strValue). That is all that is to that.
Edit on your comment: when "java properties" are not what you are looking for; then consider using other formats. For example you could be persisting your data in some JSON based format. And then just go for some existing JSON parser. Actually, your data almost looks like JSON already.
I'm not sure why you need to use ArrayList but if you want to pass these property keys/values, there are 2 better ways:
Use Properties itself.
Convert to HashMap.

Get list of attribute values from list of beans

I have a list of beans and want to obtain a list of values (given a specific attribute).
For instance, I have a list of document definitions and I want to get a list of codes:
List<DDocumentDef> childDefs = MDocumentDef.getChildDefinitions(document.getDocumentDef());
Collection<String> childCodes = new HashSet<String>();
for (DDocumentDef child : childDefs) {
childCodes.add(child.getCode());
}
Is there any more compact solution? Reflection, anonymous inner classes ...?
Thanks in advance
I feel fine with your current approach.
But if you want to add a library (e.g. apache commons-collection and commons-beanutils) or you already have added it, you can do it this way:
// create the transformer
BeanToPropertyValueTransformer transformer = new BeanToPropertyValueTransformer("code" );
// transform the Collection
Collection childCodes = CollectionUtils.collect( childDefs , transformer );
the Guava lib from google provides a similar api.
There is no other way to do this with standard Java API. However, if you are comfortable, you can use Guava's Lists.transform method:
Function<DDocumentDef, String> docToCodes =
new Function<DDocumentDef, String>() {
public String apply(DDocumentDef docDef) {
return docDef.getCode();
}
};
List<String> codes = Lists.transform(childDefs, docToCodes);
Or, wait until Java 8 is out, and then you can use lambdas and streams for this:
List<DDocumentDef> childDefs = ...
List<String> childCodes = childDefs.stream()
.map(docDef -> docDef.getCode())
.collect(Collectors.toCollection(HashSet::new));
Now it's upto you to decide, which one do you prefer, and which one do you think is shorter.

Codemodel: generic types generation in a loop .narrow()?

I am using sun-codemodel to generate code. I have problem with generics. I know that to generate something like
LinkedList<String>,
I need to use
JType jtype = jCodeModel.ref("LinkedList").narrow(jCodeModel.ref("String"));
However, how do I create something more general, for more than one generic type?
HashMap<String,Integer>
I would like to do it in the loop so that it supports any number of arguments in custom classes, but for the code like:
for(String name: names()){
returnTypeClass = jCodeModel.ref(name).narrow(jCodeModel.ref(name));
}
the output is something like this:
JNarrowedClass(JCodeModel$JReferencedClass(HashMap)<Integer>)<String>
I'm unfamiliar with CodeModel, but looking at the API documentation it seems there's a varargs overload: narrow(JClass...). Presumably this is used for resolving multiple type parameters. So in the case of HashMap<String, Integer>, you would do:
JType jtype = jCodeModel.ref("HashMap").narrow(
jCodeModel.ref("String"),
jCodeModel.ref("Integer")
);
And generalizing this to your loop:
Collection<JClass> typeArgClasses = new ArrayList<>();
for (String name : names()) {
typeArgClasses.add(jCodeModel.ref(name));
}
JType jtype = jCodeModel
.ref(typeName)
.narrow(typeArgClasses.toArray(new JClass[typeArgClasses.size()]);

Java Collections

I need to create a Hallway class which will have inside 2 ArrayLists of Stand objects , one for the stands on the right, and the other for the ones on the left.
My intention is to put these ArrayLists inside another collection in this class.
I don't know if I should use a Hashtable, a Map, etc.
More importantly, my intention is to then access these ArrayLists using a method like:
TheHashTable["Right"].add(standObject); // Add a Stand to the Right Stands ArrayList which is inside a Hashtable.
Example:
public class Hallway {
private Hashtable< String, ArrayList<<Stand> > stands;
Hallway(){
// Create 2 ArrayList<Stand>)
this.stands.put("Right", RightStands);
this.stands.put("Left", LeftStands);
}
public void addStand(Stand s){
this.stands["Right"].add(s);
}
}
Would this be possible?
It is possible, but I would advise against it. If you have only two stand locations, it would be much and clearer to simply have two variables of type List<Stand>: leftStands and rightStands, and to have corresponding methods: addLeftStand(Stand), addRightStand(Stand), etc. The code would be much clearer, simpler and safer.
If you really want to go your way, the keys of the map shouldn't be Strings. The caller wouldn't know which key to pass to your methods (there are an infinity of Strings), and ven if he knows that the keys are "Right" and "Left", he could make a typo which would go unnoticed by the compiler. You should use an enum instead, which would make the code self-documented and safer:
public enum Location {
LEFT, RIGHT
}
private Map<Location, List<Stand>> stands = new HashMap<Location, List<Stand>>();
public Hallway() {
for (Location location : Location.values()) {
stands.put(location, new ArrayList<Stand>());
}
}
public void addStand(Location location, Stand stand) {
stands.get(location).add(stand);
}
if you only have right and left, you could for example just create 2 array lists.
private ArrayList<Stand> rightStands;
private ArrayList<Stand> leftStands;
If I understood your question clearly, then this is what you want:
public void addStand(Stand s){
this.stand.get("Right").add(s);
}
But a better approach would be to use Map instead of Hashtable.
public class Hallway {
private Map< String, ArrayList<<Stand> > stands;
private List<Stand> RightStands;
private List<Stand> LeftStands;
Hallway(){
stands = new HashMap();
RightStands = new ArrayList();
LeftStands = new ArrayList();
this.stands.put("Right", RightStands);
this.stands.put("Left", LeftStands);
}
public void addStand(Stand s){
this.stands.get("Right").add(s);
}
}
You need a multi-map, for example from Commons Collections or Guava.
Those will let you map multiple values (Stand1, Stand2, ...) to a single key (e.g. "right").
For example (with Commons Collections):
MultiMap stands = new MultiHashMap();
stands.put("left", new Stand());
stands.put("left", new Stand());
stands.put("right", new Stand());
stands.put("right", new Stand());
stands.put("right", new Stand());
Collection standsOnLeftSide = (Collection) stands.get("left");
I think though that Guava is preferrable because it supports Generics.
Don't use HashTable. It has been deprecated long back. Use TreeMap or HashMap.
List<Stand> right=new ArrayList<Stand>(),left=new ArrayList<Stand>();
Map<String,List<Stand> > stands= new HashMap<String, List<Stand> >();
stands.put("right",right);
stands.put("left",left);
To learn about maps and to decide which Map suits you best read Precisely Concise: Java Maps

Categories

Resources