Filtering a Scala Set from Java - java

I want to filter a scala set from java, below is my code.
scala.collection.immutable.Set<Member> set = cluster.state().members();
Function1<Member, UniqueAddress> filter = new AbstractFunction1<Member, UniqueAddress>(){
public UniqueAddress apply(Member member){
return member.uniqueAddress();
}
};
scala.collection.immutable.Set<UniqueAddress> set1 = set.filter(filter);
But it has error with
The method filter(Function1 < Member,Object>) in the type
TraversableLike < Member,Traversable < Member>> is not applicable for the
arguments (Function1 < Member,UniqueAddress>)
How can I fix this?

After filtering a Set<Member>, you'll get a Set<Member>, not a Set<UniqueAddress>. Do you mean map? At any rate, given how Scala collections use implicits, I really wouldn't recommend working with them from Java, except by either
converting them to Java collections using JavaConversions first (but of course, this doesn't give you equivalents to map/filter/etc.), or
writing a wrapper specifically for using them from Java.

Related

How to convert a Java Collection/List to a Scala seq?

I'm trying to instantiate a Kafka Scala case class from Java code, and it has the following signature:
case class OffsetFetchRequest(groupId: String,
requestInfo: Seq[TopicAndPartition],
versionId: Short = OffsetFetchRequest.CurrentVersion,
correlationId: Int = 0,
clientId: String = OffsetFetchRequest.DefaultClientId)
I'm able to send all the requested parameters, except for the Seq[TopicAndPartition].
On the Java side, I have the following code:
OffsetFetchRequest offsetFetchRequest = new OffsetFetchRequest(
"someGroup",
topicAndPartitions,
(short)1,
1,
"clientId");
As expected, a java.util.Listis not compatible with a Scala Seq. However, I've tried all types of conversion methods in JavaConversions and JavaConverters, and I can't find anything that fits this case.
How can I create a Scala seq from a normal java.util.List or even a java.util.Collection? Or am I approaching this incorrectly?
Use scala.collection.JavaConversions.asScalaBuffer which would convert Java list to Scala buffer, of which toList method can be used to convert to immutable seq.
Alternative, you could use CyclicIterator as well.

Using Scala in Java - how to convert a Java Object to Option<Object>

I'm writing in java, and I need to use external library that is written in scala. In particular, I need the following constructor:
new PartitionMetadata(partitionId: Int, leader: Option[Broker], replicas: Seq[Broker], isr: Seq[Broker] = collection.this.Seq.empty[Nothing], errorCode: Short = kafka.common.ErrorMapping.NoError)
I was able to convert all but the leader : Option[Broker] and the Seq parameters in my java code:
partitionMetadata = new kafka.api.PartitionMetadata(
partitionId, leader.getBroker(),(Seq)brokerReplicas, (Seq)brokerIsr, errorCode);
I'm getting the following error in my editor:
'PartitionMetadata(int, scala.Option<kafka.cluster.Broker>, scala.collection.Seq<kafka.cluster.Broker>, scala.collection.Seq<kafka.cluster.Broker>, short)' in 'kafka.api.PartitionMetadata'
cannot be applied to (int, kafka.cluster.Broker, scala.collection.Seq, scala.collection.Seq, short)
Is it possible to use a Scala constructor in Java? Also, how do I convert a Java Object (leader) to a Option?
Lastly, am I converting the ArrayList -> Scala.collection.Seq fields correctly?
Thanks
Yes, it's possible to use this scala constructor in Java. The error message from your editor gives you a hint: it expects a scala.Option<kafka.cluster.Broker> as the second argument.
You can create that scala.Option as follows: scala.Option.apply(leader.getBroker())
Also, you shouldn't just cast your java array lists to scala.Seq. Instead, check out scala.collection.JavaConversions

Use fields in one tuplestream as part of regex in RegexParser on second tuplestream

I'm trying to read in a csv in the hdfs, parse it with cascading, and then use the resulting tuple stream to form the basis of regex expressions in another tuple stream using RegexParser. As far as I can tell, the only way to do this would be to write a custom Function of my own, and I was wondering if anybody knew how to use the Java API to do this instead.
Pointers on how to write my own function to do this inside the cascading framework would be welcome, too.
I'm running Cascading 2.5.1
The best resource for this question is the Palo Alto cascading example tutorial. It's in java and provides examples of a lot of use cases, including writing custom functions.
https://github.com/Cascading/CoPA/wiki
And yes, writing a function that allows an input regex that references other argument inputs is your best option.
public class SampleFunction extends BaseOperation implements Function
{
public void operate( FlowProcess flowProcess, FunctionCall functionCall )
{
TupleEntry argument = functionCall.getArguments();
String regex = argument.getString( 0 );
String argument = argument.getString( 1 );
String parsed = someRegexOperation();
Tuple result = new Tuple();
result.add( parsed );
functionCall.getOutputCollector().add( result );
}
}

Jython PyList mapping to List<String> and other Jython to Java variable mapping

how can i iterate on a Jython PyList and cast or convert my contained object to java.lang.String ?
in this old tutorial, it is done by using __ tojava __ like :
(EmployeeType)employeeObj.__tojava__(EmployeeType.class);
i suppsoe this may be something like :
PyList pywords = pythonFactoryCreatedObject.pythonMethodReturningPyList()
int count = pywords.__len__();
for (int idx = 0 ; idx < count ; idx++) {
PyObject obj = pywords.__getitem__(idx);
//here i do not know how to have a kind of 'String word = pywords[idx]' statement
//System.out.println(word);
}
is it also possible to have :
a conversion from PyList to java Array or List ? so that the construct 'for (String word : mylist) { }' can be used ?
i will have the same trouble with simple python dictionary mapping to an adequate java object, what will be the best mapping ?
Is there a tutorial doc on the java part usage of Jython ? i'm quite ok with python, but new to Java and Jython, and i found only documentation on the Java usage from Jython while i need to embed a Python module inside a Java framework...
best
PyList actually implements java.util.List<Object>, so you can use that directly from Java side.
If you fill with strings, its elements will be PyString (or maybe PyUnicode).
So:
List pywords = pythonFactoryCreatedObject.pythonMethodReturningPyList();
for (Object o : pyList){
String string = ((PyString) o).getString();
//whatever you want to do with it
}
or
List pywords = pythonFactoryCreatedObject.pythonMethodReturningPyList()
for (Object o : pyList){
String string = ((PyObject) o).__toJava__(String.class);
//whatever you want to do with it
}
whichever you find clearer.
Edit:
here's the standard doc on embedding Jython into Java. The better way to use Jython from Java would be to implement Java interfaces from Jython and manipulate the interfaces from Java, but it seems you're working with an existing Python codebase, so that wouldn't work without some changes.

Problem with ArgumentCaptor and consecutive call to same methods (bug or feature?)

I'm having a problem with ArgumentCaptor not being able to record the
arguments when calling the same method a number of times.
Basically this does not seem to work:
List<Dummy> mList = mock(List.class);
Dummy dummy = new Dummy();
when(mList.get(anyInt())).thenReturn(dummy);
Dummy d = mList.get(12);
d.setName("John");
mList.add(d);
Dummy g = mList.get(10);
g.setName("Ben");
mList.add(g);
...
verify(mymock, times(3)).doStuff(captor.capture));
assertEquals("John", captor.getAllValues().get(0).getName());
assertEquals("Ben", captor.getAllValues().get(1).getName());
assertEquals("Don", captor.getAllValues().get(2).getName());
The value of getName() is always set to "Don".
I have also tried using InOrder, with the same outcome.
Feature (and me stupiud) or bug?
To better explain the issue I have created a use case:
http://pastebin.com/RE1UzJ4F
Cheers
iwein is correct; however, there are some situations (such as embedded systems) in which memory is scarce and you do not want to use or cannot use immutability.
A workaround I have found is to use a different mock for each invocation, then verify a list of mocks that each have one invocation.
List<Mock> mocks = new ArrayList<Mock>();
...init list w/ mocks using for loop...
List<Object[]> expectedArgs = new ArrayList<Object[]>();
..init list w/ desired args...
mocks.get(0).callMethod(1, 2);
...do that some more...
for(int i = 0; i < mocks.size(); i++) {
Object[] desiredArgs = expectedArgs.get(i);
verify(mocks.get(i)).callMethod((int) desiredArgs[0], (int) desiredArgs[1]);
}
It is not as pretty, but you do not have to make your classes immutable this way.
The java doc for ArgumentCaptor suggests what you are trying, so I'd say this is a bug. However, it is a bug in your code.
The problem is that you're changing the name of the same dummy each time you're invoking setName(..). I'd suggest that you make Dummy immutable and avoid setters wherever you can. That will avoid these types of bugs.
If you cannot make your Dummy immutable to force the issue you should at least pass a different instance from each get. Doing
when(mList.get(anyInt())).thenReturn(new Dummy(), new Dummy(), new Dummy());
Would fix the problem.
I had this problem and ended up using atLeastOnce, like so:
private ActionRequest getRequestedAction() {
ArgumentCaptor<ActionRequest> captor = ArgumentCaptor.forClass(ActionRequest.class);
verify(adapter, atLeastOnce()).requestAction(captor.capture());
return captor.getValue();
}

Categories