In Java, and many other languages, one can grab a subsection of a string by saying something like String.substring(begin, end). My question is, Does there exist a built-in capability to do the same with Lists in Java that returns a sublist from the original?
This method is called subList and exists for both array and linked lists. Beware that the list it returns is backed by the existing list so updating the original one will update the slice.
The answer can be found in the List API: List#subList(int, int) (can't figure out how to get the link working....)
Be warned, though, that this is a view of the underlying list, so if you change the original list, you'll change the sublist, and the semantics of the sublist is undefined if you structurally modify the original list. So I suppose it isn't strictly what you're looking for...
If you want a structurally independent subsection of the list, I believe you'll have to do something like:
ArrayList<something> copy = new ArrayList<>(oldList.subsection(begin, end));
However, this will retain references to the original objects in the sublist. You'll probably have to manually clone everything if you want a completely new list.
The method is called sublist and can be found here in the javadocs
http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#subList(int, int)
You can use subList(start, end)
ArrayList<String> arrl = new ArrayList<String>();
//adding elements to the end
arrl.add("First");
arrl.add("Second");
arrl.add("Third");
arrl.add("Random");
arrl.add("Click");
System.out.println("Actual ArrayList:"+arrl);
List<String> list = arrl.subList(2, 4);
System.out.println("Sub List: "+list);
Ouput :
Actual ArrayList:[First, Second, Third, Random, Click]
Sub List: [Third, Random]
You might just want to make a new method if you want it to be exactly like substring is to String.
public static List<String> sub(List<String> strs, int start, int end) {
List<String> ret = new ArrayList<>(); //Make a new empty ArrayList with String values
for (int i = start; i < end; i++) { //From start inclusive to end exclusive
ret.add(strs.get(i)); //Append the value of strs at the current index to the end of ret
}
return ret;
}
public static List<String> sub(List<String> strs, int start) {
List<String> ret = new ArrayList<>(); //Make a new empty ArrayList with String values
for (int i = start; i < strs.size(); i++) { //From start inclusive to the end of strs
ret.add(strs.get(i)); //Append the value of strs at the current index to the end of ret
}
return ret;
}
If myStrings is an ArrayList of the following Strings: {"do","you","really","think","I","am","addicted","to","coding"}, then sub(myStrings,1,6) would return {"you", "really", "think", "I", "am"} and sub(myStrings,4) would return {"I", "am", "addicted", "to", "coding"}. Also by doing sub(myStrings, 0) it would rewrite myStrings as a new ArrayList which could help with referencing problems.
Related
I need to check if the certain value exists in both arrays and if exists remove this element from the second array. I know that it exists.
taking the 1st element from array doubleTue, taking the index where is this value in amTue and pmTue then remove those by using splice command.
But now my code is having problem on getting the first value.
tried as in level array: var val = doubleTue[i]
and 2 level array: var val - doubleTue[i][0]
tried toString(), read()
for (var n=0; n<doubleTue.length; n++)
{
var val = doubleTue[i][0];
var val1 = amTue.indexOf(val);
if (val1!=-1) {amTue.splice(val1, 1);};
var val2=pmTue.indexOf(val);
if (val2!=-1) {pmTue.splice(val2, 1); };
}
}
the issue is found. i have used wrong variable for looping. hehe. copy past issue
thnks all
I have following Code where i will receive list of names as parameter.In the loop, first i'm assigning index 0 value from list to local variable name. There after comparing next values from list with name. If we receive any non-equal value from list, i'm assigning value of result as 1 and failing the test case.
Below is the Array list
List<String> names= new ArrayList<String>();
names.add("John");
names.add("Mark");
Below is my selenium test method
public void test(List<String> names)
String name=null;
int a=0;
for(String value:names){
if(name==null){
System.out.println("Value is null");
name=value;
}
else if(name.equals(value)){
System.out.println("Received Same name");
name=value;
}
else{
a=1;
Assert.fail("Received different name in between");
}
}
How can i convert above code into lambda expressions?. I'm using cucumber data model, hence i receive data as list from feature file. Since i can't give clear explanation, just posted the example logic i need to convert to lambda expression.
Here's the solution: it cycles all element in your list checking if are all the same.
You can try adding or editing the list so you can have different outputs. I've written the logic, you can easly put it into a JUnit test
List<String> names= new ArrayList<>();
names.add("John");
names.add("Mark");
String firstEntry = names.get(0);
boolean allMatch = names.stream().allMatch(name -> firstEntry.equals(name));
System.out.println("All names are the same: "+allMatch);
Are you looking for duplicates, whenever you have distinct value , set a=1 and say assert to fail. You can achieve this by :
List<String> names= new ArrayList<String>();
names.add("John");
names.add("Mark");
if (names.stream().distinct().limit(2).count() > 1) {
a= 1,
Assert.fail("Received different name in between");
} else {
System.out.println("Received Same name");
}
I know jdbcTemplate can be used to create PreparedStatements if you set it up to do so:
i.e.
private JdbcTemplate jdbcTemplate;
String sqlQuery = "Select * from table where column = ?";
String value = "value";
this.jbdcTemplate.query(sqlQuery, new Object[] { value }, rs, rowNum -> {
System.out.println(rs.getString("column"));
});
However, I have a query with many AND operators in the Where clause, and depending on some condition, a specific AND statement may or may not be added to the query string.
i.e.
private JdbcTemplate jdbcTemplate;
StringBuilder sqlQuery = new StringBuilder("Select * from table where 1=1 "); //base query
if(someCondition)
sqlQuery.append("And column1 = '" + value1 + "'");
if(someCondition2)
sqlQuery.append("And column2 = '" + value2 + "'");
if(someCondition3)
sqlQuery.append("And column3 = '" + value3 + "'");
//etc...
With this type of dynamic query, I am unable to know exactly how many values to place in the new Object[] {} field at compile time, because the someCondition fields are always changing at runtime.
Is there a way to write the this.jdbcTemplate.query(sqlQuery.toString(), new Object[] {}... to accommodate these dynamic AND statements?
I found a solution after taking into consideration what #mustaccio said in his comment to my original question. I also took part of the solution from this stackoverflow question and used it in my own solution.
The main issue I was having was dynamically creating an Object[] array at runtime, since you can't dynamically add elements to an Object[] array. They must have a defined size when initialized.
First, I create an arraylist of strings called queryArgs. Every time one of the if conditions proves true and we add an AND statement to the query, I also add another line of code that adds the value to be plugged in the preparedStatement to the queryArgs arraylist. Once that's done, I create a new Object[] array whose size is initialized to the size of the queryArgs arraylist. Lastly, I loop through each element in the Object[] array, setting them equal to the values in queryArgs.
private JdbcTemplate jdbcTemplate;
List<QueryResults> jdbcQuery(QueryParams queryParams) {
/* base query */
StringBuilder sqlQuery = new StringBuilder("Select * from table where 1=1 ");
/* stores the dynamic preparedStatement arguments */
List<String> queryArgs = new ArrayList<>();
if(someCondition){
sqlQuery.append("And column1 = ? ");
queryArgs.add(queryParams.value1);
}
if(someCondition2){
sqlQuery.append("And column2 = ? ");
queryArgs.add(queryParams.value2);
}
if(someCondition3){
sqlQuery.append("And column3 = ? ");
queryArgs.add(queryParams.value3);
}
//etc...
/* this is the part I used from the above stackoverflow question */
Object[] preparedStatementArgs = new Object[queryArgs.size()];
for(int i = 0; i < preparedStatementArgs.length; i++){
preparedStatementArgs[i] = queryArgs.get(i);
}
/* Lastly, execute the query */
return this.jdbcTemplate.query(sqlQuery.toString(),
preparedStatementArgs, (rs, rowNum) -> {
QueryResults result = new QueryResults();
/* store the results of the query... */
});
}
The outlier is that one of the dynamic AND statements above is written like this:
AND column4 IN ('x','y','z','etc..')
, where the values inside of the parentheses are also dynamic at runtime. My service receives a string value that looks like this:
String queryParams.value4 = "x,y,z,etc...";
I can't write the preparedStatement like this: AND column4 IN (?) and then simply plug in queryParams.value4 because it will treat queryParams.value4 as a string literal, which leads to errors.
To solve this issue, I create another arraylist of strings called value4Array. I loop through every character in queryParams.value4, and I check if the current character in the loop is equal to a comma, our delimiter. If it is, then I create a substring of all the characters leading up to that comma, and add that newly created string to value4Array.
The next step is to create the dynamic AND column4 IN (?) statement. I do this by looping through each string value in the value4Array arraylist we just created, and doing a sql.append("?"), based on how many strings are in value4Array. After this, the rest of the logic is the same as my solution above.
/* this function takes the comma delimited string literal (value4 : "x,y,z,etc...")
and parses it into an array of strings. */
private List<String> parseValue4(String value4){
int valueIndex= 0;
List<String> value4Array = new ArrayList<>();
for(int i = 0; i < value4.length(); i++){
if(value4.charAt(i) == ','){
value4Array.add(value4.substring(valueIndex, i));
valueIndex = i + 1;
}
else if(i == value4.length() - 1){
value4Array.add(value4.substring(valueIndex, value4.length()));
}
}
return value4Array;
}
if(someCondition4){
List<String> value4Array = parseValue4(queryParams.value4);
sqlQuery.append("And column4 IN ("); /* base AND statement */
for(int i = 0; i < value4Array.size(); i++){
if(i == value4Array.size() - 1)
sqlQuery.append("?)");
else /* dynamically appending ?'s */
sqlQuery.append("?,");
queryArgs.add(value4Array.get(i));
}
}
You are taking list of string type (List<String> queryArgs = new ArrayList<>();).
What if the parameter is an integer type? Is there any way to store multiple typle of data?
Supposed that I have two arrays:
Dim RoomName() As String = {(RoomA), (RoomB), (RoomC), (RoomD), (RoomE)}
Dim RoomType() As Integer = {1, 2, 2, 2, 1}
I want to get a value from the "RoomName" array based on a criteria of "RoomType" array. For example, I want to get a "RoomName" with "RoomType = 2", so the algorithm should randomize the index of the array that the "RoomType" is "2", and get a single value range from index "1-3" only.
Is there any possible ways to solve the problem using array, or is there any better ways to do this? Thank you very much for your time :)
Note: Code examples below using C# but hopefully you can read the intent for vb.net
Well, a simpler way would be to have a structure/class that contained both name and type properties e.g.:
public class Room
{
public string Name { get; set; }
public int Type { get; set; }
public Room(string name, int type)
{
Name = name;
Type = type;
}
}
Then given a set of rooms you can find those of a given type using a simple linq expression:
var match = rooms.Where(r => r.Type == 2).Select(r => r.Name).ToList();
Then you can find a random entry from within the set of matching room names (see below)
However assuming you want to stick with the parallel arrays, one way is to find the matching index values from the type array, then find the matching names and then find one of the matching values using a random function.
var matchingTypeIndexes = new List<int>();
int matchingTypeIndex = -1;
do
{
matchingTypeIndex = Array.IndexOf(roomType, 2, matchingTypeIndex + 1);
if (matchingTypeIndex > -1)
{
matchingTypeIndexes.Add(matchingTypeIndex);
}
} while (matchingTypeIndex > -1);
List<string> matchingRoomNames = matchingTypeIndexes.Select(typeIndex => roomName[typeIndex]).ToList();
Then to find a random entry of those that match (from one of the lists generated above):
var posn = new Random().Next(matchingRoomNames.Count);
Console.WriteLine(matchingRoomNames[posn]);
I have a list:
Dim list As New List(Of String)
with the following items:
290-7-11
1255-7-12
222-7-11
290-7-13
What's an easy and fast way to search if duplicate of "first block" plus "-" plus "second block" is already in the list. Example the item 290-7 appears twice, 290-7-11 and 290-7-13.
I am using .net 2.0
If you only want to know if there are duplicates but don't care what they are...
The easiest way (assuming exactly two dashes).
Boolean hasDuplicatePrefixes = list
.GroupBy(i => i.Substring(0, i.LastIndexOf('-')))
.Any(g => g.Count() > 1)
The fastest way (at least for large sets of strings).
HashSet<String> hashSet = new HashSet<String>();
Boolean hasDuplicatePrefixes = false;
foreach (String item in list)
{
String prefix = item.Substring(0, item.LastIndexOf('-'));
if (hashSet.Contains(prefix))
{
hasDuplicatePrefixes = true;
break;
}
else
{
hashSet.Add(prefix);
}
}
If there are cases with more than two dashes, use the following. This will still fail with a single dash.
String prefix = item.Substring(0, item.IndexOf('-', item.IndexOf('-') + 1));
In .NET 2.0 use Dictionary<TKey, TValue> instead of HashSet<T>.
Dictionary<String, Boolean> dictionary= new Dictionary<String, Boolean>();
Boolean hasDuplicatePrefixes = false;
foreach (String item in list)
{
String prefix = item.Substring(0, item.LastIndexOf('-'));
if (dictionary.ContainsKey(prefix))
{
hasDuplicatePrefixes = true;
break;
}
else
{
dictionary.Add(prefix, true);
}
}
If you don't care about readability and speed, use an array instead of a list, and you are a real fan of regular expressions, you can do the following, too.
Boolean hasDuplicatePrefixes = Regex.IsMatch(
String.Join("#", list), #".*(?:^|#)([0-9]+-[0-9]+-).*#\1");
Do you want to stop user from adding it?
If so, a HashTable with the key as first block-second block could be of use.
If not, LINQ is the way to go.
But, it will have to traverse the list to check.
How big can this list be?
EDIT: I don't know if HashTable has generic version.
You could also use SortedDictionary which can take generic arguments.
If you're list contains only strings, then you can simply make a method that takes the string you want to find along with the list:
Boolean isStringDuplicated(String find, List<String> list)
{
if (list == null)
throw new System.ArgumentNullException("Given list is null.");
int count = 0;
foreach (String s in list)
{
if (s.Contains(find))
count += 1;
if (count == 2)
return true;
}
return false;
}
If you're numbers have a special significance in your program, don't be afraid to use a class to represent them instead of sticking with strings. Then you would have a place to write all the custom functionality you want for said numbers.